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.