Operador "(+)" de Oracle


155

Estoy revisando algunas declaraciones SQL antiguas con el propósito de documentarlas y probablemente mejorarlas.

El DBMS es Oracle

No entendí una declaración que decía así:

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

Estoy confundido sobre el (+)operador, y no pude encontrarlo en ningún foro ... (la búsqueda de + entre comillas tampoco funcionó).

De todos modos, usé 'Explain Plan' de SQLDeveloper y obtuve un resultado que decía eso HASH JOIN, RIGHT OUTER, etc.

¿Habría alguna diferencia si elimino el (+)operador al final de la consulta? ¿La base de datos tiene que cumplir alguna condición (como tener algunos índices, etc.) antes de (+)poder usarse? Sería de gran ayuda si me puede proporcionar una comprensión simple, o algunos buenos enlaces donde puedo leer sobre esto.

¡Gracias!


1
No es un operador. Es solo una sintaxis que afecta lo que JOIN hace.
philipxy

Respuestas:


187

Esa es la notación específica de Oracle para un OUTER JOIN, porque el formato ANSI-89 (usando una coma en la cláusula FROM para separar las referencias de tabla) no estandarizó las uniones OUTER.

La consulta se volvería a escribir en la sintaxis ANSI-92 como:

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

Este enlace es bastante bueno para explicar la diferencia entre JOIN .


También debe tenerse en cuenta que a pesar de que (+)funciona, Oracle recomienda no usarlo :

Oracle recomienda que utilice la sintaxis de la FROMcláusula en OUTER JOINlugar del operador de unión de Oracle. Las consultas de combinación externa que utilizan el operador de combinación de Oracle (+)están sujetas a las siguientes reglas y restricciones, que no se aplican a la sintaxis de la FROMcláusula OUTER JOIN:


79
Exactamente correcto. Para mantener el (+) derecho en mi cabeza (lado izquierdo vs. lado derecho), me gusta pensar en el (+) como "agregar valores NULL si no se encuentra ninguna coincidencia". Por ejemplo, "a.id = b.id (+)" significa permitir que b.id sea NULL si no hay coincidencia con a.id.
playa

gracias ... Supongo que agregarlo desde la cláusula debería producir el mismo resultado.
Kiran S

Es posible que desee tener un enlace en la documentación oficial de Oracle: docs.oracle.com/html/A95915_01/sqopr.htm
Vargan

27

El operador (+) indica una unión externa. Esto significa que Oracle aún devolverá registros del otro lado de la unión, incluso cuando no haya coincidencia. Por ejemplo, si ayb son emp y dept y usted puede tener empleados no asignados a un departamento, la siguiente declaración devolverá detalles de todos los empleados, ya sea que hayan sido asignados o no a un departamento.

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

En resumen, eliminar el (+) puede marcar una diferencia significativa, ¡pero es posible que no lo notes por un tiempo dependiendo de tus datos!


25

En Oracle, (+) denota la tabla "opcional" en JOIN. Entonces en tu consulta,

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

es una IZQUIERDA EXTERIOR IZQUIERDA de la tabla 'b' a la tabla 'a'. Devolverá todos los datos de la tabla 'a' sin perder sus datos cuando el otro lado (tabla opcional 'b') no tenga datos.

Diagrama de la unión externa izquierda

La sintaxis estándar moderna para la misma consulta sería

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

o con una abreviatura de a.id=b.id(no compatible con todas las bases de datos):

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

Si elimina (+), será una consulta de unión interna normal

Sintaxis anterior, tanto en Oracle como en otras bases de datos:

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

Sintaxis más moderna:

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

O simplemente:

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

Diagrama de unión interna

Solo devolverá todos los datos donde el valor 'id' de las tablas 'a' y 'b' sea el mismo, significa parte común.

Si desea hacer que su consulta sea correcta

Esto es lo mismo que un LEFT JOIN, pero cambia qué tabla es opcional.

Diagrama de unión externa derecha

Antigua sintaxis de Oracle:

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

Sintaxis estándar moderna:

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

Ref y ayuda:

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

Unión externa izquierda usando el signo + en Oracle 11g

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


Las etiquetas de círculo "tabla1" y "tabla2" no tienen sentido. El significado más simple para los elementos del círculo son las filas de salida. Luego, la media luna izquierda contiene las filas nulas extendidas de la tabla1 y la media luna derecha contiene las filas nulas extendidas de la tabla2. Otros significados para los círculos son oscuros. ¿Qué crees que significan exactamente los diagramas? ¿Por qué los pones en otra parte que no sea copiar a ciegas las presentaciones (malas) de otras personas?
philipxy

Ahora ha etiquetado los círculos a y b. Los círculos no son filas de a & b. Los círculos izquierdo y derecho podrían etiquetarse razonablemente como filas de una unión izquierda b y una unión derecha b. Además, no describe cuáles son esas filas encerradas en términos de la entrada. Averigua por ti mismo qué cosas hay en los círculos. Si va a pegar las etiquetas a & b en los círculos, explique claramente en palabras qué tiene que ver cada etiqueta con su círculo. (No hay una razón directa para etiquetarlos como a & b.) Es bueno que haya etiquetado correctamente las zonas verdes.
philipxy

6

En la práctica, el símbolo + se coloca directamente en la declaración condicional y en el lado de la tabla opcional (la que puede contener valores vacíos o nulos dentro del condicional).


El (+) se coloca inmediatamente a la derecha del nombre de una columna. Esta respuesta no está clara al respecto. ¿Qué se supone que significa "en la práctica"? (Retórica.) (Y probablemente no quiere decir "declaración".)
Filipinas
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.