sql >> Database >  >> RDS >> PostgreSQL

Oracle naar PostgreSQL:ANSI outer join-syntaxis in PostgreSQL

We bevinden ons bij het derde artikel in de Oracle-migratiereeks. Deze keer kijken we naar die vreemde operators die de WHERE-clausulecriteria in Oracle (+) wijzigen. Net als al het andere heeft PostgreSQL daar een oplossing voor.

RIGHT JOIN

Oracle ondersteunt, en veel ontwikkelaars gebruiken, ANSI outer JOIN-syntaxis met behulp van operators voor de kwalificatieclausule.

Meestal ziet dat er ongeveer zo uit:

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

Het doel van deze syntaxis is een rechter outer join. In termen van verzamelingentheorie is dit de subset inclusief alle plaatsen, ongeacht de persoon.

Het resultaat van een kleine steekproef zou er als volgt uitzien:

id achternaam first_name id locatie person_id
1 (NULL) (NULL) 1 Dallas (NULL)
2 Roybal Kirk 2 Londen 2
3 Riggs Simon 3 Parijs 3

Deze syntaxis wordt niet ondersteund in PostgreSQL.

Om hetzelfde resultaat te bereiken, gebruikt u de standaard SQL-syntaxis voor outer joins.

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

SQL biedt ook een verduidelijkend bijwoord OUTER . Deze verduidelijking is volledig optioneel, zoals elke RIGHT JOIN is per definitie een OUTER doe mee.

VOLLEDIGE JOIN

Evenzo werkt het gebruik van de Oracle-syntaxis voor een volledige join niet in PostgreSQL.

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

Het doel van deze syntaxis is een volledige lijst van personen en plaatsen, ongeacht of een persoon aan een plaats is gekoppeld of niet.

Het resultaat ziet er als volgt uit:

id achternaam first_name** id locatie person_id
1 (NULL) (NULL) 1 Dallas (NULL)
2 Roybal Kirk 2 Londen 2
3 Riggs Simon 3 Parijs 3
4 Andrew Dunstan (NULL) (NULL) (NULL)

Met behulp van de PostgreSQL-syntaxis zou de query als volgt worden geschreven:

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

Nogmaals, de OUTER zoekwoord is volledig optioneel.

CROSS JOIN

Een duidelijk voordeel van het gebruik van zoekwoorden in plaats van impliciete relaties is dat u niet per ongeluk een cross-product kunt maken.

De syntaxis:

SELECT *
FROM persons
LEFT JOIN places;

Zal resulteren in een fout:

ERROR:  syntax error at or near ";"

Geeft aan dat de instructie niet compleet is bij de regeleindemarkering ";".

PostgreSQL zal het cross join-product maken met behulp van de ANSI-syntaxis.

SELECT *
FROM persons, places;
id achternaam voornaam id locatie person_id
1 Dunstan Andrew 1 Dallas (null)
1 Dunstan Andrew 2 Londen 2
1 Dunstan Andrew 3 Parijs 3
1 Dunstan Andrew 4 Madrid (null)
2 Koninklijke Kirk 1 Dallas (null)
2 Koninklijke Kirk 2 Londen 2
2 Koninklijke Kirk 3 Parijs 3
2 Koninklijke Kirk 4 Madrid (null)
3 Riggs Simon 1 Dallas (null)
3 Riggs Simon 2 Londen 2
3 Riggs Simon 3 Parijs 3
3 Riggs Simon 4 Madrid (null)
6 Wong Markeren 1 Dallas (null)
6 Wong Markeren 2 Londen 2
6 Wong Markeren 3 Parijs 3
6 Wong Markeren 4 Madrid (null)

Dat is waarschijnlijker een codeerfout dan het opzettelijke resultaat.

Om deze functionaliteit opzettelijk te krijgen, wordt aanbevolen om de CROSS JOIN . te gebruiken verklaring.

SELECT *
FROM persons
CROSS JOIN places;

Zo is het ondubbelzinnig wat er in de verklaring werd bedoeld.

NATUURLIJKE JOIN

PostgreSQL ondersteunt de NATURAL JOIN syntaxis, maar een beetje onder protest.

SELECT *
FROM persons
NATURAL JOIN places;

Dit levert het volgende resultaat op.

id achternaam voornaam ouder_id locatie person_id
1 Dunstan Andrew (null) Dallas (null)
2 Koninklijke Kirk 1 Londen 2
3 Riggs Simon 1 Parijs 3

Deze syntaxis is echter een probleem. Voor ons voorbeeld heeft de kolom "id" in beide tabellen niets met elkaar te maken . Deze samenvoeging heeft een resultaat opgeleverd, maar wel een met volledig irrelevante inhoud.

Bovendien kunt u een zoekopdracht hebben die in eerste instantie het juiste resultaat geeft, maar latere DDL-instructies hebben een stille invloed.

Overweeg:

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

Welke kolom is nu de NATURAL JOIN gebruik makend van? De keuzes zijn id, places_id, person_id en al het bovenstaande. Ik laat het antwoord als oefening aan de lezer over.

Deze syntaxis is een tijdbom voor uw code. Gebruik het gewoon niet.

Oké, dus je bent niet overtuigd. Nou, dan heb je tenminste wat zinnige codeerconventies. Geef voor de bovenliggende tabel de identiteitskolom de naam "myparenttable_id". Wanneer u ernaar verwijst vanuit onderliggende relaties, gebruikt u dezelfde naam, "mijnoudertabel_id". Noem nooit iets "id", en verwijs nooit naar een kolom met een andere naam. Ach, vergeet het maar. Doe dit gewoon niet.

U kunt in de verleiding komen om de vorige puzzel ondubbelzinnig te maken door de USING . te gebruiken trefwoord. Dat zou er zo uitzien:

SELECT *
FROM persons
JOIN places
USING (id);

Maar de USING trefwoord kan alleen profiteren van exacte naamovereenkomsten in tabellen. Wat nogmaals, in ons voorbeeld is gewoon helemaal verkeerd.

De beste keuze voor PostgreSQL is om simpelweg het ontwerpen van tabellen te vermijden door conventiestandaarden te coderen.

Samenvatting

Deze trefwoordtechnieken (vs. operators) zijn ook beschikbaar op Oracle. Ze zijn meer platformonafhankelijk en minder dubbelzinnig. Dat alleen al zou hen tot de beste praktijken maken.

Daar komt nog bij dat ze logische fouten blootleggen bij oneigenlijk gebruik. Voor elke ontwikkeling in PostgreSQL raden we eenzijdig aan om expliciete trefwoorden te gebruiken.


  1. Hoe maak je een ja/nee boolean veld in SQL server?

  2. MySQL InnoDB Cluster 8.0 - Een complete implementatie-walk-through:deel één

  3. Oracle SQL - REGEXP_LIKE bevat andere tekens dan a-z of A-Z

  4. SQL DROP DATABASE-syntaxis - weergegeven door DBMS