PostgreSQL
 sql >> Base de Dados >  >> RDS >> PostgreSQL

Oracle para PostgreSQL:sintaxe de junção externa ANSI no PostgreSQL


Chegamos ao terceiro artigo da série de migração da Oracle. Desta vez, olhamos para aqueles operadores estranhos que modificam os critérios da cláusula WHERE no Oracle (+). Como tudo, o PostgreSQL tem uma solução para isso.

RIGHT JOIN


A Oracle suporta, e muitos desenvolvedores usam, a sintaxe ANSI outer JOIN usando operadores para a cláusula de qualificação.

Normalmente, isso se parece com isso:
SELECT *
FROM person, places
WHERE person.id = places.person_id(+)

O objetivo desta sintaxe é uma junção externa direita. Em termos da teoria dos conjuntos, este é o subconjunto que inclui todos os lugares, independentemente da pessoa.





O resultado de uma pequena amostra ficaria assim:
id last_name first_name id local person_id
1 (NULL) (NULL) 1 Dallas (NULO)
2 Roybal Kirk 2 Londres 2
3 Riggs Simão 3 Paris 3

Esta sintaxe não é suportada no PostgreSQL.

Para obter o mesmo resultado, você usaria a sintaxe SQL padrão para associações externas.
SELECT *
FROM persons
RIGHT JOIN places
ON persons.id = places.person_id;

SQL também fornece um advérbio esclarecedor OUTER . Este clarificador é completamente opcional, como qualquer RIGHT JOIN é por definição um OUTER Junte-se.

UNIÇÃO COMPLETA


Da mesma forma, usar a sintaxe do Oracle para uma junção completa não funciona no PostgreSQL.
SELECT *
FROM persons, places
WHERE persons.id(+) = places(+);

O objetivo desta sintaxe é uma lista completa de pessoas e lugares, independentemente de uma pessoa estar associada a um lugar ou não.





O resultado ficaria assim:
id last_name first_name** id local person_id
1 (NULL) (NULL) 1 Dallas (NULO)
2 Roybal Kirk 2 Londres 2
3 Riggs Simão 3 Paris 3
4 André Dunstan (NULO) (NULL) (NULO)

Usando a sintaxe do PostgreSQL, a consulta seria escrita assim:
SELECT *
FROM persons
FULL JOIN places
ON persons.id = places.person_id;

Novamente, o OUTER palavra-chave é completamente opcional.

CROSS JOIN


Uma vantagem distinta da abordagem de usar palavras-chave em vez de relacionamentos implícitos é que você não pode criar acidentalmente um produto cruzado.

A sintaxe:
SELECT *
FROM persons
LEFT JOIN places;

Resultará em um erro:
ERROR:  syntax error at or near ";"

Indicando que a instrução não está completa no marcador final de linha “;”.

O PostgreSQL criará o produto de junção cruzada usando a sintaxe ANSI.


SELECT *
FROM persons, places;
id sobrenome first_name código local person_id
1 Dunstan André 1 Dallas (nulo)
1 Dunstan André 2 Londres 2
1 Dunstan André 3 Paris 3
1 Dunstan André 4 Madri (nulo)
2 Roybal Kirk 1 Dallas (nulo)
2 Roybal Kirk 2 Londres 2
2 Roybal Kirk 3 Paris 3
2 Roybal Kirk 4 Madri (nulo)
3 Riggs Simão 1 Dallas (nulo)
3 Riggs Simão 2 Londres 2
3 Riggs Simão 3 Paris 3
3 Riggs Simão 4 Madri (nulo)
6 Wong Marcar 1 Dallas (nulo)
6 Wong Marcar 2 Londres 2
6 Wong Marcar 3 Paris 3
6 Wong Marcar 4 Madri (nulo)

O que é mais provável um erro de codificação do que o resultado intencional.

Para obter essa funcionalidade intencionalmente, é recomendável usar o CROSS JOIN demonstração.
SELECT *
FROM persons
CROSS JOIN places;

Tornando assim inequívoco o que se quis dizer na declaração.

UNIÇÃO NATURAL


PostgreSQL suporta o NATURAL JOIN sintaxe, mas um pouco sob protesto.
SELECT *
FROM persons
NATURAL JOIN places;

Isso produz o seguinte resultado.
id sobrenome first_name parent_id local person_id
1 Dunstan André (nulo) Dallas (nulo)
2 Roybal Kirk 1 Londres 2
3 Riggs Simão 1 Paris 3

No entanto, essa sintaxe é um problema. Para o nosso exemplo, a coluna "id" em ambas as tabelas não tem nada a ver uma com a outra . Essa junção produziu um resultado, mas com conteúdo completamente irrelevante.

Além disso, você pode ter uma consulta que apresenta inicialmente o resultado correto, mas as instruções DDL subsequentes afetam silenciosamente.

Considerar:
ALTER TABLE person ADD COLUMN places_id bigint;
ALTER TABLE places ADD COLUMN places_id bigint;
ALTER TABLE person ADD COLUMN person_id bigint;

Agora, qual coluna é o NATURAL JOIN usando? As opções são id, places_id, person_id e todas as opções acima. Deixo a resposta como exercício para o leitor.

Essa sintaxe é uma bomba-relógio para o seu código. Só não use.

Ok, então você não está convencido. Bem, então pelo menos tenha algumas convenções de codificação sãs. Para a tabela pai, nomeie a coluna de identidade como “myparenttable_id”. Ao referenciar a partir de relações filho, use o mesmo nome, “myparenttable_id”. Nunca nomeie nada como “id” e nunca faça referência a uma coluna com um nome diferente. Ah, esqueça. Apenas não faça isso.

Você pode ficar tentado a desambiguar o quebra-cabeça anterior usando o USING palavra-chave. Isso ficaria assim:
SELECT *
FROM persons
JOIN places
USING (id);

Mas o USING A palavra-chave só pode aproveitar as correspondências de nome exatas nas tabelas. O que novamente, em nosso exemplo, está totalmente errado.

A escolha de melhor prática para o PostgreSQL é simplesmente evitar projetar tabelas por padrões de convenção de codificação.

Resumo


Essas técnicas de palavras-chave (vs. operadores) também estão disponíveis no Oracle. Eles são mais multiplataforma e menos ambíguos. Isso por si só os tornaria melhores práticas.

Somado a isso, expõem erros lógicos quando utilizados de forma inadequada. Para qualquer desenvolvimento no PostgreSQL, recomendamos unilateralmente o uso de palavras-chave explícitas.