sql >> Database teknologi >  >> RDS >> PostgreSQL

Oracle til PostgreSQL:ANSI ydre joinsyntaks i PostgreSQL

Vi befinder os i den tredje artikel i Oracle-migreringsserien. Denne gang ser vi på de mærkelige operatorer, der ændrer WHERE-sætningskriterierne i Oracle (+). Som alt andet har PostgreSQL en løsning til det.

HØJRE JOIN

Oracle understøtter, og mange udviklere bruger, ANSI ydre JOIN-syntaks ved hjælp af operatorer til kvalifikationsklausulen.

Typisk ser det sådan ud:

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

Formålet med denne syntaks er en højre ydre sammenføjning. I mængdeteoretiske termer er dette delmængden inklusive alle steder, uanset person.

Resultatet af en lille prøve ville se sådan ud:

id efternavn fornavn id placering person_id
1 (NULL) (NULL) 1 Dallas (NULL)
2 Roybal Kirk 2 London 2
3 Riggs Simon 3 Paris 3

Denne syntaks er ikke understøttet i PostgreSQL.

For at opnå det samme resultat, ville du bruge standard SQL-syntaks for outer joins.

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

SQL giver også et opklarende adverbium OUTER . Denne clarifier er fuldstændig valgfri, som enhver RIGHT JOIN er per definition en OUTER deltage.

FULD JOIN

På samme måde virker det ikke i PostgreSQL at bruge Oracle-syntaksen til en fuld joinforbindelse.

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

Formålet med denne syntaks er en komplet liste over personer og steder, uanset om en person er forbundet med et sted eller ej.

Resultatet vil gerne være sådan her:

id efternavn fornavn** id placering person_id
1 (NULL) (NULL) 1 Dallas (NULL)
2 Roybal Kirk 2 London 2
3 Riggs Simon 3 Paris 3
4 Andrew Dunstan (NULL) (NULL) (NULL)

Ved at bruge PostgreSQL-syntaks ville forespørgslen blive skrevet således:

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

Igen, OUTER søgeord er helt valgfrit.

CROSS JOIN

En klar fordel ved tilgangen til at bruge søgeord frem for implicitte relationer er, at du ikke ved et uheld er i stand til at skabe et krydsprodukt.

Syntaksen:

SELECT *
FROM persons
LEFT JOIN places;

Vil resultere i en fejl:

ERROR:  syntax error at or near ";"

Indikerer, at sætningen ikke er komplet ved linjeafslutningsmarkøren ";".

PostgreSQL vil oprette cross join-produktet ved hjælp af ANSI-syntaksen.

SELECT *
FROM persons, places;
id efternavn fornavn id placering person_id
1 Dunstan Andrew 1 Dallas (nul)
1 Dunstan Andrew 2 London 2
1 Dunstan Andrew 3 Paris 3
1 Dunstan Andrew 4 Madrid (nul)
2 Roybal Kirk 1 Dallas (nul)
2 Roybal Kirk 2 London 2
2 Roybal Kirk 3 Paris 3
2 Roybal Kirk 4 Madrid (nul)
3 Riggs Simon 1 Dallas (nul)
3 Riggs Simon 2 London 2
3 Riggs Simon 3 Paris 3
3 Riggs Simon 4 Madrid (nul)
6 Wong Mærk 1 Dallas (nul)
6 Wong Mærk 2 London 2
6 Wong Mærk 3 Paris 3
6 Wong Mærk 4 Madrid (nul)

Hvilket er mere sandsynligt en kodefejl end det tilsigtede resultat.

For at få denne funktionalitet med vilje, anbefales det at bruge CROSS JOIN erklæring.

SELECT *
FROM persons
CROSS JOIN places;

Dermed er det utvetydigt, hvad der menes i erklæringen.

NATURLIG JOIN

PostgreSQL understøtter NATURAL JOIN syntaks, men lidt under protest.

SELECT *
FROM persons
NATURAL JOIN places;

Dette giver følgende resultat.

id efternavn fornavn parent_id placering person_id
1 Dunstan Andrew (nul) Dallas (nul)
2 Roybal Kirk 1 London 2
3 Riggs Simon 1 Paris 3

Denne syntaks er dog et problem. For vores eksempel har "id"-kolonnen i begge tabeller intet med hinanden at gøre . Denne deltagelse har givet et resultat, men et med fuldstændig irrelevant indhold.

Derudover har du muligvis en forespørgsel, der til at begynde med præsenterer det korrekte resultat, men efterfølgende DDL-sætninger påvirker lydløst.

Overvej:

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

Hvilken kolonne er nu NATURAL JOIN ved brug af? Valgene er id, steder_id, person_id og alle ovenstående. Jeg overlader svaret som en øvelse til læseren.

Denne syntaks er en tidsindstillet bombe for din kode. Bare lad være med at bruge det.

Ok, så du er ikke overbevist. Nå, så har du i det mindste nogle fornuftige kodningskonventioner. For den overordnede tabel skal du navngive identitetskolonnen "myparenttable_id". Når du refererer til det fra underordnede relationer, skal du bruge det samme navn, "myparenttable_id". Navngiv aldrig noget "id", og giv aldrig en henvisning til en kolonne med et andet navn. Ah, glem det. Bare lad være med at gøre dette.

Du kan blive fristet til at udelukke det forrige puslespil ved at bruge USING søgeord. Det ville se sådan ud:

SELECT *
FROM persons
JOIN places
USING (id);

Men USING søgeord kan kun drage fordel af eksakte navnematches på tværs af tabeller. Hvilket igen i vores eksempel bare er helt forkert.

Det bedste valg for PostgreSQL er simpelthen at undgå at designe tabeller ved at kode konventionsstandarder.

Oversigt

Disse søgeordsteknikker (i forhold til operatører) er også tilgængelige på Oracle. De er mere på tværs af platforme og mindre tvetydige. Det alene ville gøre dem til bedste praksis.

Derudover afslører de logiske fejl, når de bruges forkert. For enhver udvikling i PostgreSQL anbefaler vi ensidigt at bruge eksplicitte søgeord.


  1. Skift sikkerhedsgruppe på AWS RDS-databaseinstans

  2. ProxySQL Native Clustering med Kubernetes

  3. Databasedesign:ét stort bord eller separate tabeller?

  4. SQL Indfyld tabel med tilfældige data