sql >> Databáze >  >> RDS >> PostgreSQL

Oracle to PostgreSQL:Syntaxe vnějšího spojení ANSI v PostgreSQL

Ocitáme se u třetího článku série migrace Oracle. Tentokrát se podíváme na ty podivné operátory, které upravují kritéria klauzule WHERE v Oracle (+). Jako všechno ostatní, i na to má PostgreSQL řešení.

SPRÁVNÉ PŘIPOJENÍ

Oracle podporuje a mnoho vývojářů používá vnější syntaxi ANSI JOIN pomocí operátorů v kvalifikační klauzuli.

Obvykle to vypadá nějak takto:

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

Cílem této syntaxe je pravé vnější spojení. Z hlediska teorie množin je to podmnožina zahrnující všechna místa bez ohledu na osobu.

Výsledek malého vzorku by vypadal takto:

id příjmení křestní_jméno id umístění person_id
1 (NULL) (NULL) 1 Dallas (NULL)
2 Roybal Kirk 2 Londýn 2
3 Riggs Simon 3 Paříž 3

Tato syntaxe není v PostgreSQL podporována.

K dosažení stejného výsledku byste použili standardní syntaxi SQL pro vnější spojení.

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

SQL také poskytuje objasňující příslovce OUTER . Tento objasňovač je zcela volitelný, stejně jako jakékoli RIGHT JOIN je z definice OUTER připojte se.

PLNÉ PŘIPOJENÍ

Podobně použití syntaxe Oracle pro úplné spojení nefunguje v PostgreSQL.

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

Cílem této syntaxe je úplný seznam osob a míst bez ohledu na to, zda je osoba s místem spojena nebo ne.

Výsledek by vypadal takto:

id příjmení křestní_jméno** id umístění person_id
1 (NULL) (NULL) 1 Dallas (NULL)
2 Roybal Kirk 2 Londýn 2
3 Riggs Simon 3 Paříž 3
4 Andrew Dunstan (NULL) (NULL) (NULL)

Pomocí syntaxe PostgreSQL by byl dotaz napsán takto:

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

Opět OUTER klíčové slovo je zcela nepovinné.

CROSS JOIN

Jednou výraznou výhodou přístupu k používání klíčových slov namísto implicitních vztahů je to, že nemůžete náhodně vytvořit křížový produkt.

Syntaxe:

SELECT *
FROM persons
LEFT JOIN places;

Výsledkem bude chyba:

ERROR:  syntax error at or near ";"

Indikuje, že příkaz není úplný na značce konce řádku „;“.

PostgreSQL vytvoří produkt křížového spojení pomocí syntaxe ANSI.

SELECT *
FROM persons, places;
id last_name first_name id místo person_id
1 Dunstan Andrej 1 Dallas (null)
1 Dunstan Andrew 2 Londýn 2
1 Dunstan Andrew 3 Paříž 3
1 Dunstan Andrej 4 Madrid (null)
2 Roybal Kirk 1 Dallas (null)
2 Roybal Kirk 2 Londýn 2
2 Roybal Kirk 3 Paříž 3
2 Roybal Kirk 4 Madrid (null)
3 Riggs Simon 1 Dallas (null)
3 Riggs Simon 2 Londýn 2
3 Riggs Simon 3 Paříž 3
3 Riggs Simon 4 Madrid (null)
6 Wong Označit 1 Dallas (null)
6 Wong Označit 2 Londýn 2
6 Wong Označit 3 Paříž 3
6 Wong Označit 4 Madrid (null)

Což je pravděpodobnější chyba v kódování než záměrný výsledek.

Chcete-li tuto funkci získat záměrně, doporučujeme použít CROSS JOIN prohlášení.

SELECT *
FROM persons
CROSS JOIN places;

Tím je jednoznačné, co bylo v prohlášení myšleno.

NATURAL JOIN

PostgreSQL podporuje NATURAL JOIN syntaxe, ale trochu pod protestem.

SELECT *
FROM persons
NATURAL JOIN places;

Výsledkem je následující.

id last_name first_name parent_id místo person_id
1 Dunstan Andrew (null) Dallas (null)
2 Roybal Kirk 1 Londýn 2
3 Riggs Simon 1 Paříž 3

Tato syntaxe je však problém. V našem příkladu sloupec „id“ v obou tabulkách nemá nic společného . Toto spojení přineslo výsledek, ale se zcela irelevantním obsahem.

Navíc můžete mít dotaz, který zpočátku prezentuje správný výsledek, ale následné příkazy DDL tiše ovlivní.

Zvažte:

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

Nyní, který sloupec je NATURAL JOIN použitím? Možnosti jsou id, places_id, person_id a všechny výše uvedené. Odpověď nechám jako cvičení na čtenáři.

Tato syntaxe je pro váš kód časovanou bombou. Prostě to nepoužívejte.

Dobře, takže nejste přesvědčeni. No, pak alespoň mějte nějaké rozumné kódovací konvence. Pro nadřazenou tabulku pojmenujte sloupec identity „myparenttable_id“. Když na něj odkazujete z podřízených vztahů, použijte stejný název, „myparenttable_id“. Nikdy nic nepojmenujte „id“ a nikdy neodkazujte na sloupec s jiným názvem. Zapomeň na to. Prostě to nedělej.

Můžete být v pokušení rozdělit předchozí hádanku pomocí USING klíčové slovo. To by vypadalo takto:

SELECT *
FROM persons
JOIN places
USING (id);

Ale USING klíčové slovo může využívat pouze přesné shody názvů napříč tabulkami. Což je opět v našem příkladu naprosto špatné.

Nejlepší volbou pro PostgreSQL je jednoduše se vyhnout navrhování tabulek pomocí standardů konvence kódování.

Přehled

Tyto techniky klíčových slov (vs. operátory) jsou také dostupné na Oracle. Jsou více multiplatformní a méně nejednoznačné. To samo o sobě by z nich udělalo osvědčené postupy.

Navíc při nesprávném použití odhalují logické chyby. Pro jakýkoli vývoj v PostgreSQL jednostranně doporučujeme používat explicitní klíčová slova.


  1. Jak vytvořit omezení Not Null ve sloupci v tabulce SQL Server - SQL Server / Výukový program T-SQL, část 51

  2. Proč se řádky vrácené vysvětlením nerovnají count()?

  3. Získejte velikost všech databází v PostgreSQL (psql)

  4. Jak mohu vygenerovat jedinečný řetězec na záznam v tabulce v Postgres?