Operador Oracle “(+)”


155

Estou verificando algumas antigas instruções SQL com o objetivo de documentá-las e provavelmente aprimorá-las.

O DBMS é Oracle

Não entendi uma declaração que tenha a seguinte redação:

select ...
from a,b
where a.id=b.id(+)

Estou confuso sobre o (+)operador e não consegui encontrá-lo em nenhum fórum ... (procurar + entre aspas também não funcionou).

De qualquer forma, usei o 'Explain Plan' do SQLDeveloper e obtive uma saída dizendo isso HASH JOIN, RIGHT OUTER, etc.

Haveria alguma diferença se eu remover o (+)operador no final da consulta? O banco de dados precisa atender a alguma condição (como ter alguns índices etc.) antes de (+)poder ser usado? Seria muito útil se você pudesse me fornecer uma compreensão simples ou alguns bons links onde eu possa ler sobre isso.

Obrigado!


1
Não é um operador. É apenas uma parte da sintaxe que afeta o que o JOIN faz.
philipxy

Respostas:


187

Essa é a notação específica do Oracle para uma OUTER JOIN, porque o formato ANSI-89 (usando uma vírgula na cláusula FROM para separar as referências da tabela) não padroniza as junções OUTER.

A consulta seria reescrita na sintaxe ANSI-92 como:

   SELECT ...
     FROM a
LEFT JOIN b ON b.id = a.id

Este link é muito bom para explicar a diferença entre JOINs .


Deve-se notar também que, embora (+)funcione, a Oracle recomenda não usá-lo :

A Oracle recomenda que você use a sintaxe da FROMcláusula OUTER JOINem vez do operador de junção do Oracle. As consultas de junção externa que usam o operador de junção Oracle (+)estão sujeitas às seguintes regras e restrições, que não se aplicam à sintaxe da FROMcláusula OUTER JOIN:


79
Exatamente certo. Para manter o (+) reto na minha cabeça (lado esquerdo vs. lado direito), eu gosto de pensar no (+) como "adicionar valores NULL se nenhuma correspondência encontrada". Por exemplo, "a.id = b.id (+)" significa permitir que b.id seja NULL se não houver correspondência com a.id.
praia

obrigado .. Eu acho que adicioná-lo da cláusula deve produzir o mesmo resultado !!
Kiran S

Você pode querer ter um link na documentação oficial Oracle: docs.oracle.com/html/A95915_01/sqopr.htm
Vargan

27

O operador (+) indica uma junção externa. Isso significa que o Oracle ainda retornará registros do outro lado da junção, mesmo quando não houver correspondência. Por exemplo, se aeb são emp e departamento e você pode ter funcionários não atribuídos a um departamento, a declaração a seguir retornará detalhes de todos os funcionários, independentemente de terem sido atribuídos ou não a um departamento.

select * from emp, dept where emp.dept_id=dept.dept_id(+)

Resumindo, remover o (+) pode fazer uma diferença significativa, mas você pode não perceber por um tempo, dependendo dos seus dados!


25

No Oracle, (+) indica a tabela "opcional" em JOIN. Então, na sua consulta,

SELECT a.id, b.id, a.col_2, b.col_2, ...
FROM a,b
WHERE a.id=b.id(+)

é uma junção externa esquerda da tabela 'b' para a tabela 'a'. Ele retornará todos os dados da tabela 'a' sem perder seus dados quando o outro lado (tabela opcional 'b') não tiver dados.

Diagrama da junção externa esquerda

A sintaxe padrão moderna para a mesma consulta seria

SELECT  a.id, b.id, a.col_2, b.col_2, ...
FROM a
LEFT JOIN b ON a.id=b.id

ou com um atalho para a.id=b.id(não suportado por todos os bancos de dados):

SELECT  a.id, b.id, a.col_2, b.col_2, ...
FROM a
LEFT JOIN b USING(id)

Se você remover (+), será uma consulta de junção interna normal

Sintaxe mais antiga, no Oracle e em outros bancos de dados:

SELECT  a.id, b.id, a.col_2, b.col_2, ...
FROM a,b
WHERE a.id=b.id

Sintaxe mais moderna:

SELECT  a.id, b.id, a.col_2, b.col_2, ...
FROM a
INNER JOIN b ON a.id=b.id

Ou simplesmente:

SELECT  a.id, b.id, a.col_2, b.col_2, ...
FROM a
JOIN b ON a.id=b.id

Diagrama da junção interna

Ele retornará apenas todos os dados onde o valor 'id' da tabela 'a' e 'b' for igual, significa parte comum.

Se você deseja fazer da sua consulta uma Junta Direita

É exatamente o mesmo que LEFT JOIN, mas alterna qual tabela é opcional.

Diagrama da junção externa direita

Sintaxe antiga do Oracle:

SELECT  a.id, b.id, a.col_2, b.col_2, ...
FROM a,b
WHERE a.id(+)=b.id

Sintaxe padrão moderna:

SELECT  a.id, b.id, a.col_2, b.col_2, ...
FROM a
RIGHT JOIN b ON a.id=b.id

Referência e ajuda:

https://asktom.oracle.com/pls/asktom/f?p=100:11:::::P11_QUESTION_ID:6585774577187

Junção externa esquerda usando o sinal + no Oracle 11g

https://www.w3schools.com/sql/sql_join_left.asp


Os rótulos de círculo "tabela1" e "tabela2" não fazem sentido. O significado mais simples para elementos do círculo são linhas de saída. Em seguida, o crescente esquerdo contém as linhas estendidas nulas da tabela1 e o crescente direito as linhas estendidas nulas da tabela2. Outros significados para os círculos são obscuros. O que exatamente você acha que os diagramas significam? Por que você os colocou além de copiar cegamente as apresentações (ruins) de outras pessoas?
precisa saber é

Você já rotulou os círculos como a & b. Os círculos não são linhas de a & b. Os círculos esquerdo e direito poderiam ser razoavelmente rotulados como linhas de uma junção esquerda b e uma junção direita b. Além disso, você não descreve o que são essas linhas circundadas em termos de entrada. Descubra por si mesmo quais são as coisas nos círculos. Se você quiser colocar os rótulos a e b nos círculos, explique claramente em palavras o que cada rótulo tem a ver com seu círculo. (Não há motivo simples para rotulá-los como a & b.) É bom que você tenha rotulado as zonas verdes corretamente.
philipxy

6

Na prática, o símbolo + é colocado diretamente na instrução condicional e ao lado da tabela opcional (aquela que pode conter valores vazios ou nulos dentro da condicional).


O (+) é colocado imediatamente à direita do nome de uma coluna. Esta resposta não está clara sobre isso. O que "na prática" deveria significar? (Retórica.) (E você provavelmente não quer dizer "declaração".)
philipxy
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.