Nous nous retrouvons au troisième article de la série Oracle migration. Cette fois, nous regardons ces opérateurs étranges qui modifient les critères de la clause WHERE dans Oracle (+). Comme tout le reste, PostgreSQL a une solution pour cela.
JOINTURE DROITE
Oracle prend en charge, et de nombreux développeurs l'utilisent, la syntaxe JOIN externe ANSI en utilisant des opérateurs pour la clause de qualification.
En règle générale, cela ressemble à ceci :
SELECT *
FROM person, places
WHERE person.id = places.person_id(+)
L'objectif de cette syntaxe est une jointure externe droite. En termes de théorie des ensembles, il s'agit du sous-ensemble comprenant tous les lieux, quelle que soit la personne.
Le résultat d'un petit échantillon ressemblerait à ceci :
id | nom_de_famille | first_name | identifiant | emplacement | id_personne |
---|---|---|---|---|---|
1 | (NULL) | (NULL) | 1 | Dallas | (NULL) |
2 | Roybal | Kirk | 2 | Londres | 2 |
3 | Riggs | Simon | 3 | Paris | 3 |
Cette syntaxe n'est pas prise en charge dans PostgreSQL.
Pour obtenir le même résultat, vous utiliseriez la syntaxe SQL standard pour les jointures externes.
SELECT *
FROM persons
RIGHT JOIN places
ON persons.id = places.person_id;
SQL fournit également un adverbe de clarification OUTER
. Ce clarificateur est complètement facultatif, comme tout RIGHT JOIN
est par définition un OUTER
rejoindre.
JOINTURE COMPLÈTE
De même, l'utilisation de la syntaxe Oracle pour une jointure complète ne fonctionne pas dans PostgreSQL.
SELECT *
FROM persons, places
WHERE persons.id(+) = places(+);
L'objectif de cette syntaxe est une liste complète des personnes et des lieux, qu'une personne soit associée ou non à un lieu.
Le résultat ressemblerait à ceci :
id | nom_de_famille | first_name** | identifiant | emplacement | id_personne |
---|---|---|---|---|---|
1 | (NULL) | (NULL) | 1 | Dallas | (NULL) |
2 | Roybal | Kirk | 2 | Londres | 2 |
3 | Riggs | Simon | 3 | Paris | 3 |
4 | André | Dunstan | (NULL) | (NULL) | (NULL) |
En utilisant la syntaxe PostgreSQL, la requête s'écrirait ainsi :
SELECT *
FROM persons
FULL JOIN places
ON persons.id = places.person_id;
Encore une fois, le OUTER
mot-clé est complètement facultatif.
JOINTURE CROISÉE
L'un des avantages distincts de l'approche consistant à utiliser des mots-clés plutôt que des relations implicites est que vous ne pouvez pas créer accidentellement un produit croisé.
La syntaxe :
SELECT *
FROM persons
LEFT JOIN places;
Entraînera une erreur :
ERROR: syntax error at or near ";"
Indique que l'instruction n'est pas complète au marqueur de fin de ligne ";".
PostgreSQL créera le produit de jointure croisée en utilisant la syntaxe ANSI.
SELECT *
FROM persons, places;
identifiant | nom_de_famille | prénom | identifiant | person_id | |
---|---|---|---|---|---|
1 | Dunstan | André | 1 | Dallas | (null) |
1 | Dunstan | André | 2 | Londres | 2 |
1 | Dunstan | André | 3 | Paris | 3 |
1 | Dunstan | André | 4 | Madrid | (null) |
2 | Roybal | Kirk | 1 | Dallas | (null) |
2 | Roybal | Kirk | 2 | Londres | 2 |
2 | Roybal | Kirk | 3 | Paris | 3 |
2 | Roybal | Kirk | 4 | Madrid | (null) |
3 | Riggs | Simon | 1 | Dallas | (null) |
3 | Riggs | Simon | 2 | Londres | 2 |
3 | Riggs | Simon | 3 | Paris | 3 |
3 | Riggs | Simon | 4 | Madrid | (null) |
6 | Wong | Marquer | 1 | Dallas | (null) |
6 | Wong | Marquer | 2 | Londres | 2 |
6 | Wong | Marquer | 3 | Paris | 3 |
6 | Wong | Marquer | 4 | Madrid | (null) |
Ce qui est plus probablement une erreur de codage que le résultat intentionnel.
Pour obtenir cette fonctionnalité intentionnellement, il est recommandé d'utiliser le CROSS JOIN
déclaration.
SELECT *
FROM persons
CROSS JOIN places;
Ce qui rend sans ambiguïté ce qui était signifié dans la déclaration.
JOINTURE NATURELLE
PostgreSQL supporte le NATURAL JOIN
syntaxe, mais un peu sous la protestation.
SELECT *
FROM persons
NATURAL JOIN places;
Cela produit le résultat suivant.
identifiant | nom_de_famille | prénom | identifiant_parent | person_id | |
---|---|---|---|---|---|
1 | Dunstan | André | (null) | Dallas | (null) |
2 | Roybal | Kirk | 1 | Londres | 2 |
3 | Riggs | Simon | 1 | Paris | 3 |
Cependant, cette syntaxe pose problème. Pour notre exemple, la colonne "id" dans les deux tables n'a rien à voir l'une avec l'autre . Cette jointure a produit un résultat, mais avec un contenu complètement hors de propos.
De plus, vous pouvez avoir une requête qui présente initialement le résultat correct, mais les instructions DDL suivantes affectent silencieusement.
Considérez :
ALTER TABLE person ADD COLUMN places_id bigint;
ALTER TABLE places ADD COLUMN places_id bigint;
ALTER TABLE person ADD COLUMN person_id bigint;
Maintenant, quelle colonne est le NATURAL JOIN
en utilisant? Les choix sont id, places_id, person_id et tout ce qui précède. Je vais laisser la réponse en exercice au lecteur.
Cette syntaxe est une bombe à retardement pour votre code. Ne l'utilisez pas.
Ok, donc vous n'êtes pas convaincu. Eh bien, ayez au moins quelques conventions de codage saines. Pour la table parent, nommez la colonne d'identité "myparenttable_id". Lorsque vous le référencez à partir de relations enfants, utilisez le même nom, "myparenttable_id". Ne nommez jamais rien "id", et ne faites jamais référence à une colonne avec un nom différent. Ah, oublie ça. Ne fais pas ça.
Vous pourriez être tenté de désambiguïser le puzzle précédent en utilisant le USING
mot-clé. Cela ressemblerait à ceci :
SELECT *
FROM persons
JOIN places
USING (id);
Mais le USING
Le mot-clé ne peut tirer parti que des correspondances de noms exactes entre les tables. Ce qui encore une fois, dans notre exemple, est tout simplement faux.
Le meilleur choix de pratique pour PostgreSQL consiste simplement à éviter de concevoir des tables en codant des normes de convention.
Résumé
Ces techniques de mots-clés (vs opérateurs) sont également disponibles sur Oracle. Ils sont plus multiplateformes et moins ambigus. Cela seul en ferait les meilleures pratiques.
De plus, ils exposent des erreurs logiques lorsqu'ils sont mal utilisés. Pour tout développement dans PostgreSQL, nous recommandons unilatéralement d'utiliser des mots clés explicites.