PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

Oracle zu PostgreSQL:ANSI Outer Join-Syntax in PostgreSQL

Wir befinden uns beim dritten Artikel in der Oracle-Migrationsserie. Dieses Mal sehen wir uns diese seltsamen Operatoren an, die die Kriterien der WHERE-Klausel in Oracle (+) ändern. Wie alles andere hat auch PostgreSQL dafür eine Lösung.

RECHTSVERBINDUNG

Oracle unterstützt und viele Entwickler verwenden die äußere JOIN-Syntax von ANSI, die Operatoren für die Qualifikationsklausel verwendet.

Normalerweise sieht das so aus:

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

Das Ziel dieser Syntax ist ein Right Outer Join. In der Mengenlehre ist dies die Teilmenge, die alle Orte umfasst, unabhängig von der Person.

Das Ergebnis einer kleinen Stichprobe würde so aussehen:

id Nachname Vorname ID Standort Personen-ID
1 (NULL) (NULL) 1 Dallas (NULL)
2 Roybal Kirk 2 London 2
3 Riggs Simon 3 Paris 3

Diese Syntax wird in PostgreSQL nicht unterstützt.

Um dasselbe Ergebnis zu erzielen, würden Sie die Standard-SQL-Syntax für äußere Verknüpfungen verwenden.

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

SQL bietet auch ein klarstellendes Adverb OUTER . Diese Klarstellung ist völlig optional, wie jeder RIGHT JOIN ist per Definition ein OUTER beitreten.

VOLLSTÄNDIGER JOIN

Ebenso funktioniert die Verwendung der Oracle-Syntax für einen vollständigen Join in PostgreSQL nicht.

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

Das Ziel dieser Syntax ist eine vollständige Liste von Personen und Orten, unabhängig davon, ob eine Person einem Ort zugeordnet ist oder nicht.

Das Ergebnis sähe so aus:

id Nachname Vorname** ID Standort Personen-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)

Unter Verwendung der PostgreSQL-Syntax würde die Abfrage folgendermaßen geschrieben:

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

Wieder das OUTER Schlüsselwort ist völlig optional.

CROSS JOIN

Ein entscheidender Vorteil der Verwendung von Schlüsselwörtern anstelle von impliziten Beziehungen besteht darin, dass Sie nicht versehentlich ein Kreuzprodukt erstellen können.

Die Syntax:

SELECT *
FROM persons
LEFT JOIN places;

Führt zu einem Fehler:

ERROR:  syntax error at or near ";"

Zeigt an, dass die Anweisung an der Zeilenendmarkierung „;“.

nicht vollständig ist

PostgreSQL erstellt das Cross-Join-Produkt unter Verwendung der ANSI-Syntax.

SELECT *
FROM persons, places;
id Nachname Vorname id Standort Personen-ID
1 Dunstan Andrew 1 Dallas (null)
1 Dunstan Andrew 2 London 2
1 Dunstan Andrew 3 Paris 3
1 Dunstan Andrew 4 Madrid (null)
2 Royal Kirch 1 Dallas (null)
2 Royal Kirch 2 London 2
2 Royal Kirch 3 Paris 3
2 Royal Kirch 4 Madrid (null)
3 Rigs Simon 1 Dallas (null)
3 Rigs Simon 2 London 2
3 Rigs Simon 3 Paris 3
3 Rigs Simon 4 Madrid (null)
6 Wong Markieren 1 Dallas (null)
6 Wong Markieren 2 London 2
6 Wong Markieren 3 Paris 3
6 Wong Markieren 4 Madrid (null)

Was eher ein Codierungsfehler als das absichtliche Ergebnis ist.

Um diese Funktionalität absichtlich zu erhalten, wird empfohlen, den CROSS JOIN zu verwenden Aussage.

SELECT *
FROM persons
CROSS JOIN places;

Dadurch wird eindeutig, was in der Aussage gemeint war.

NATÜRLICHER JOIN

PostgreSQL unterstützt den NATURAL JOIN Syntax, aber etwas unter Protest.

SELECT *
FROM persons
NATURAL JOIN places;

Dies führt zu folgendem Ergebnis.

id Nachname Vorname parent_id Standort Personen-ID
1 Dunstan Andrew (null) Dallas (null)
2 Royal Kirch 1 London 2
3 Rigs Simon 1 Paris 3

Diese Syntax ist jedoch ein Problem. In unserem Beispiel hat die Spalte „id“ in beiden Tabellen nichts miteinander zu tun . Diese Verknüpfung hat ein Ergebnis hervorgebracht, aber eines mit völlig irrelevantem Inhalt.

Darüber hinaus haben Sie möglicherweise eine Abfrage, die anfänglich das richtige Ergebnis liefert, aber nachfolgende DDL-Anweisungen unbemerkt beeinflussen.

Bedenken Sie:

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

Welche Spalte ist nun der NATURAL JOIN verwenden? Zur Auswahl stehen id, places_id, person_id und alle oben genannten. Die Antwort überlasse ich dem Leser als Übung.

Diese Syntax ist eine Zeitbombe für Ihren Code. Verwenden Sie es einfach nicht.

Ok, also bist du nicht überzeugt. Nun, dann haben Sie zumindest einige vernünftige Codierungskonventionen. Benennen Sie für die übergeordnete Tabelle die Identitätsspalte „myparenttable_id“. Wenn Sie von untergeordneten Beziehungen darauf verweisen, verwenden Sie denselben Namen, „myparenttable_id“. Nennen Sie niemals etwas „id“ und verweisen Sie niemals auf eine Spalte mit einem anderen Namen. Ach, vergiss es. Tu das einfach nicht.

Sie könnten versucht sein, das vorherige Rätsel mit dem USING eindeutiger zu machen Stichwort. Das würde so aussehen:

SELECT *
FROM persons
JOIN places
USING (id);

Aber die USING Das Schlüsselwort kann nur exakte Namensübereinstimmungen über Tabellen hinweg nutzen. Was wiederum in unserem Beispiel absolut falsch ist.

Die Best-Practice-Wahl für PostgreSQL besteht darin, einfach das Entwerfen von Tabellen nach Codierungskonventionsstandards zu vermeiden.

Zusammenfassung

Diese Schlüsselworttechniken (im Vergleich zu Operatoren) sind auch auf Oracle verfügbar. Sie sind plattformübergreifender und weniger mehrdeutig. Das allein würde sie zu Best Practices machen.

Hinzu kommt, dass sie bei unsachgemäßer Verwendung logische Fehler aufdecken. Für jede Entwicklung in PostgreSQL empfehlen wir einseitig die Verwendung expliziter Schlüsselwörter.