sql >> Base de Datos >  >> RDS >> PostgreSQL

Oracle a PostgreSQL:sintaxis de unión externa ANSI en PostgreSQL

Nos encontramos en el tercer artículo de la serie de migración de Oracle. En esta ocasión, nos fijamos en esos extraños operadores que modifican los criterios de la cláusula WHERE en Oracle (+). Como todo lo demás, PostgreSQL tiene una solución para eso.

RIGHT JOIN

Oracle admite, y muchos desarrolladores la utilizan, la sintaxis externa JOIN de ANSI utilizando operadores en la cláusula de calificaciones.

Por lo general, se parece a esto:

SELECT *
FROM person, places
WHERE person.id = places.person_id(+)

El objetivo de esta sintaxis es una combinación externa derecha. En términos de teoría de conjuntos, este es el subconjunto que incluye todos los lugares, independientemente de la persona.

El resultado de una pequeña muestra se vería así:

id apellido nombre id ubicación id_persona
1 (NULO) (NULO) 1 Dallas (NULO)
2 Roybal Kirk 2 Londres 2
3 Riggs Simón 3 París 3

Esta sintaxis no es compatible con PostgreSQL.

Para lograr el mismo resultado, usaría la sintaxis SQL estándar para combinaciones externas.

SELECT *
FROM persons
RIGHT JOIN places
ON persons.id = places.person_id;

SQL también proporciona un adverbio aclaratorio OUTER . Este clarificador es completamente opcional, como cualquier RIGHT JOIN es por definición un OUTER unirse.

UNIÓN COMPLETA

De manera similar, el uso de la sintaxis de Oracle para una unión completa no funciona en PostgreSQL.

SELECT *
FROM persons, places
WHERE persons.id(+) = places(+);

El objetivo de esta sintaxis es una lista completa de personas y lugares, ya sea que una persona esté asociada con un lugar o no.

El resultado sería así:

id apellido primer_nombre** id ubicación id_persona
1 (NULO) (NULO) 1 Dallas (NULO)
2 Roybal Kirk 2 Londres 2
3 Riggs Simón 3 París 3
4 Andrés Dunstan (NULO) (NULO) (NULO)

Usando la sintaxis de PostgreSQL, la consulta se escribiría así:

SELECT *
FROM persons
FULL JOIN places
ON persons.id = places.person_id;

De nuevo, el OUTER la palabra clave es completamente opcional.

UNIÓN CRUZADA

Una clara ventaja del enfoque de usar palabras clave en lugar de relaciones implícitas es que no puede crear accidentalmente un producto cruzado.

La sintaxis:

SELECT *
FROM persons
LEFT JOIN places;

Dará como resultado un error:

ERROR:  syntax error at or near ";"

Indicando que la declaración no está completa en el marcador de final de línea ";".

PostgreSQL creará el producto de unión cruzada utilizando la sintaxis ANSI.

SELECT *
FROM persons, places;
id apellido nombre identificación ubicación id_persona
1 Dunstan Andrés 1 Dallas (nulo)
1 Dunstan Andrés 2 Londres 2
1 Dunstan Andrés 3 París 3
1 Dunstan Andrés 4 Madrid (nulo)
2 Royal Kirk 1 Dallas (nulo)
2 Royal Kirk 2 Londres 2
2 Royal Kirk 3 París 3
2 Royal Kirk 4 Madrid (nulo)
3 Riggs Simón 1 Dallas (nulo)
3 Riggs Simón 2 Londres 2
3 Riggs Simón 3 París 3
3 Riggs Simón 4 Madrid (nulo)
6 Wong Marcar 1 Dallas (nulo)
6 Wong Marcar 2 Londres 2
6 Wong Marcar 3 París 3
6 Wong Marcar 4 Madrid (nulo)

Lo cual es más probable que sea un error de codificación que el resultado intencional.

Para obtener esta funcionalidad intencionalmente, se recomienda usar CROSS JOIN declaración.

SELECT *
FROM persons
CROSS JOIN places;

De este modo, queda claro lo que se quiere decir en la declaración.

UNIÓN NATURAL

PostgreSQL es compatible con NATURAL JOIN sintaxis, pero un poco bajo protesta.

SELECT *
FROM persons
NATURAL JOIN places;

Esto produce el siguiente resultado.

id apellido nombre parent_id ubicación id_persona
1 Dunstan Andrés (nulo) Dallas (nulo)
2 Royal Kirk 1 Londres 2
3 Riggs Simón 1 París 3

Sin embargo, esta sintaxis es un problema. Para nuestro ejemplo, la columna "id" en ambas tablas no tiene nada que ver entre sí . Esta unión ha producido un resultado, pero uno con contenido completamente irrelevante.

Además, es posible que tenga una consulta que inicialmente presente el resultado correcto, pero que las declaraciones DDL subsiguientes afecten silenciosamente.

Considere:

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

Ahora, ¿qué columna es NATURAL JOIN? ¿utilizando? Las opciones son id, places_id, person_id y todas las anteriores. Dejaré la respuesta como ejercicio para el lector.

Esta sintaxis es una bomba de relojería para su código. Simplemente no lo uses.

Ok, entonces no estás convencido. Bueno, entonces al menos tenga algunas convenciones de codificación sanas. Para la tabla principal, asigne a la columna de identidad el nombre "myparenttable_id". Cuando haga referencia a él desde relaciones secundarias, use el mismo nombre, "myparenttable_id". Nunca nombre nada como "id", y nunca haga referencia a una columna con un nombre diferente. Ah, olvídalo. Simplemente no hagas esto.

Puede tener la tentación de eliminar la ambigüedad del acertijo anterior usando el USING palabra clave. Eso se vería así:

SELECT *
FROM persons
JOIN places
USING (id);

Pero el USING La palabra clave solo puede aprovechar las coincidencias exactas de nombres en las tablas. Lo cual, de nuevo, en nuestro ejemplo está totalmente equivocado.

La mejor opción de práctica para PostgreSQL es simplemente evitar el diseño de tablas mediante estándares de convenciones de codificación.

Resumen

Estas técnicas de palabras clave (vs. operadores) también están disponibles en Oracle. Son más multiplataforma y menos ambiguos. Solo eso los convertiría en las mejores prácticas.

Sumado a eso, exponen errores lógicos cuando se usan incorrectamente. Para cualquier desarrollo en PostgreSQL, recomendamos unilateralmente el uso de palabras clave explícitas.