Um JOIN NATURAL é uma operação JOIN que cria uma cláusula de junção implícita para você com base nas colunas comuns nas duas tabelas que estão sendo unidas. Uma junção NATURAL pode ser uma junção INNER, uma junção LEFT OUTER ou uma junção RIGHT OUTER. O padrão é junção INNER. Fonte
Portanto, uma junção natural pode ser uma forma abreviada de implementar a junção interna se ambas as tabelas tiverem uma coluna comum.
Considere a seguinte tabela:
SELECT * FROM t1;
/*
ID PLANET
---------- --------
1 jupiter
2 earth
*/
Unimos a tabela a ela mesma:
SELECT first.id, first.planet FROM t1 first INNER JOIN t1 second ON first.id=second.id;
/*
ID PLANET
---------- --------
1 jupiter
2 earth
*/
Tente fazer o mesmo com a notação de junção natural:
SELECT id, planet FROM t1 NATURAL JOIN t1;
/*
ID PLANET
---------- --------
1 jupiter
1 jupiter
2 earth
2 earth
*/
Dado que a junção natural aqui é implementada usando a junção interna, por que as várias linhas?
Atualizar:
A execução da mesma junção com aliases de tabela tem uma saída diferente:
SELECT id, planet FROM t1 first NATURAL JOIN t1 second;
/*
ID PLANET
---------- --------
1 jupiter
2 earth
*/
O banco de dados Oracle não entende a sintaxe de junção ANSI internamente (exceto
FULL OUTER JOIN
), ele reescreve essas consultas para sua própria sintaxe de junção antiga. Se você habilitar o rastreamento do otimizador, por exemplo:E execute as consultas, no arquivo de rastreamento gerado, você pode visualizar a forma final da consulta que é executada.
é transformado em (BP é meu esquema):
E
é transformado em:
E este é o problema,
"T1"."PLANET"="T1"."PLANET" AND "T1"."ID"="T1"."ID"
.Mas não me pergunte por que, é apenas uma daquelas coisas "inexplicáveis" no Oracle.
Eu vi um caso em que a transformação resultou em uma consulta final igualmente ambígua, e houve uma mensagem de erro real no arquivo de rastreamento, ainda assim, o banco de dados retornou resultados errados e nenhum erro para o cliente.
Parece um bug.
Primeiro, um self
x NATURAL JOIN x
deve retornar o mesmo número de linhas e colunas que a tabela original. Portanto, a última consulta que retorna 2 linhas está correta. A 2ª consulta, que retorna 4 linhas, parece estar fazendo umCROSS JOIN
(se você tentar com uma tabela de 3 linhas, ela retornará 9).Segundo, a consulta deveria ter dado um
"ORA-00918: column ambiguously defined"
erro ou algo parecido porque não é permitido ter 2 tabelas com o mesmo alias na mesmaFROM
cláusula.Veja os testes em dbfiddle.uk , onde as junções cruzadas retornam esta mensagem de erro:
e as mesmas consultas testadas no Postgres :