web-dev-qa-db-fra.com

Oracle Joins - Comparaison entre la syntaxe conventionnelle et la syntaxe ANSI

Préambule

Ces derniers temps, je vois trop de geeks commenter des questions Oracle disant que "N'utilisez pas d'opérateur (+), utilisez plutôt la syntaxe JOIN".

Question

Je vois que les deux fonctionnent bien. Mais quelle est la vraie différence entre les utiliser et qu'est-ce qui vous fait ressentir de les utiliser? Je serais heureux de recevoir des réponses, davantage par expérience.

 1. Is there anything to do with limitations in application, performance, 
    etc. while using them?

 2. What would you suggest for me?

J'ai lu quelque chose sur documentation Oracle mais pas assez bon pour me faire comprendre ou me sentir à l'aise avec les informations complètes.

Remarque : Je prévois de migrer plus de 200 packages et procédures, si le mot-clé doit être utilisé à la place de (+)

  3. Also is there any freeware tools to do the rewrite?

Publication d'échantillons

┌───────────────────────────────────┬─────────────────────────────────────────────┐
│ INNER JOIN - CONVENTIONAL         │ INNER JOIN - ANSI SYNTAX                    │
├───────────────────────────────────┼─────────────────────────────────────────────┤
│ SELECT                            │ SELECT                                      │
│      emp.deptno                   │       ename,                                │
│ FROM                              │       dname,                                │
│      emp,                         │       emp.deptno,                           │
│      dept                         │       dept.deptno                           │
│ WHERE                             │ FROM                                        │
│      emp.deptno = dept.deptno;    │       scott.emp INNER JOIN scott.dept       │
│                                   │       ON emp.deptno = dept.deptno;          │
├───────────────────────────────────┼─────────────────────────────────────────────┤
│ LEFT OUTER JOIN - CONVENTIONAL    │ LEFT OUTER JOIN - ANSI SYNTAX               │
├───────────────────────────────────┼─────────────────────────────────────────────┤
│ SELECT                            │ SELECT                                      │
│      emp.deptno                   │      ename,                                 │
│ FROM                              │      dname,                                 │
│      emp,                         │      emp.deptno,                            │
│      dept                         │      dept.deptno                            │
│ WHERE                             │ FROM                                        │
│      emp.deptno = dept.deptno(+); │      scott.emp LEFT OUTER JOIN scott.dept   │
│                                   │      ON emp.deptno = dept.deptno;           │
├───────────────────────────────────┼─────────────────────────────────────────────┤
│ RIGHT OUTER JOIN - CONVENTIONAL   │ RIGHT OUTER JOIN - ANSI SYNTAX              │
├───────────────────────────────────┼─────────────────────────────────────────────┤
│ SELECT                            │ SELECT                                      │
│      emp.deptno                   │      ename,                                 │
│ FROM                              │      dname,                                 │
│      emp,                         │      emp.deptno,                            │
│      dept                         │      dept.deptno                            │
│ WHERE                             │ FROM                                        │
│      emp.deptno(+) = dept.deptno; │      scott.emp RIGHT OUTER JOIN scott.dept  │
│                                   │      ON emp.deptno = dept.deptno;           │
├───────────────────────────────────┼─────────────────────────────────────────────┤
│ FULL OUTER JOIN - CONVENTIONAL    │ FULL OUTER JOIN - ANSI SYNTAX               │
├───────────────────────────────────┼─────────────────────────────────────────────┤
│ SELECT                            │ SELECT                                      │
│      *                            │      *                                      │
│ FROM                              │ FROM                                        │
│      emp,                         │      scott.emp FULL OUTER JOIN scott.dept   │
│      dept                         │      ON emp.deptno = dept.deptno;           │
│ WHERE                             │                                             │
│      emp.deptno = dept.deptno(+)  │                                             │
│ UNION ALL                         │                                             │
│ SELECT                            │                                             │
│      *                            │                                             │
│ FROM                              │                                             │
│      emp,                         │                                             │
│      dept                         │                                             │
│ WHERE                             │                                             │
│      emp.deptno(+) = dept.deptno  │                                             │
│      AND emp.deptno IS NULL;      │                                             │
└───────────────────────────────────┴─────────────────────────────────────────────┘

[~ # ~] ps [~ # ~] : Lisez le résumé des réponses pour toutes les mises à jour groupées.

28
SriniV

Regroupement des réponses

  1. Utiliser des jointures explicites plutôt qu'implicites (qu'il s'agisse de jointures externes ou non), c'est qu'il est beaucoup plus facile de créer accidentellement un produit cartésien avec les jointures implicites. Avec des JOIN explicites, vous ne pouvez pas en créer "par accident". Plus il y a de tables impliquées, plus le risque est que vous manquiez une condition de jointure.
  2. Fondamentalement (+) est sévèrement limité par rapport aux jointures ANSI. De plus, il n'est disponible que dans Oracle tandis que la syntaxe de jointure ANSI est prise en charge par tous les principaux SGBD
  3. SQL ne commencera pas à mieux fonctionner après la migration vers la syntaxe ANSI - c'est juste une syntaxe différente.
  4. Oracle vous recommande fortement d'utiliser la syntaxe de jointure de clause FROM plus flexible indiquée dans l'exemple précédent. Dans le passé, il y avait quelques bugs avec la syntaxe ANSI mais si vous utilisez la dernière version 11.2 ou 12.1, cela devrait déjà être corrigé.
  5. L'utilisation des opérateurs JOIN garantit que votre code SQL est conforme à ANSI et permettrait ainsi de porter plus facilement une application frontale pour d'autres plateformes de base de données.
  6. Les conditions de jointure ont une très faible sélectivité sur chaque table et une haute sélectivité sur les tuples dans le produit vectoriel théorique. Les conditions de l'instruction where ont généralement une sélectivité beaucoup plus élevée.
  7. Oracle convertit en interne la syntaxe ANSI en syntaxe (+), vous pouvez le voir dans la section Informations sur les prédicats du plan d'exécution.

Piège possible dans l'utilisation de la syntaxe ANSI sur le moteur 12c

Y compris une possibilité de bug dans JOIN en 12c. Voir ici

SUIVI:

Quest SQL optimizer tool réécrit la syntaxe SQL vers ANSI.

9
SriniV

Si vos 200+ packages fonctionnent comme prévu avec la syntaxe "à l'ancienne", que ce soit. SQL ne commencera pas à mieux fonctionner après la migration vers la syntaxe ANSI - c'est juste une syntaxe différente.

Cela étant dit, la syntaxe ANSI est plus propre - vous n'allez pas à la jointure normale si vous oubliez (+) dans une jointure externe à plusieurs colonnes.
Dans le passé, il y avait quelques bogues avec la syntaxe ANSI mais si vous utilisez la dernière version 11.2 ou 12.1, cela devrait déjà être corrigé.
Bien sûr, vous connaissez mieux votre environnement et vos priorités - comme l'a dit SchmitzIT - la syntaxe ANSI fait partie de la norme SQL et elle vous serait utile lorsque vous utiliserez un autre produit SGBDR.

24
igr

Dans 11g, vous devriez utiliser la syntaxe de jointure ANSI. Il est plus flexible (prise en charge des jointures externes complètes et des jointures partitionnées) et, comme l'indique la documentation:

Oracle vous recommande fortement d'utiliser la syntaxe de jointure de clause FROM plus flexible indiquée dans l'exemple précédent.

C'est une raison suffisante.

14
David Aldridge

En dehors des raisons mentionnées par d'autres, l'utilisation des opérateurs JOIN garantit que votre code SQL est conforme à ANSI et permettrait ainsi de porter plus facilement une application frontale pour d'autres plates-formes de base de données.

5
SchmitzIT

En pratique, vous devez toujours utiliser la syntaxe ANSI. Mieux vaut ne pas retravailler sur les packages et les procédures. Vous pouvez plutôt corriger les choses lorsque vous effectuez une maintenance sur ces scripts individuellement. Il n'y aura aucune différence dans les plans en raison de la syntaxe.

L'optimiseur Quest SQL réécrit avec toutes les combinaisons possibles pour trouver un meilleur plan. Vous devez donc toujours rechercher un SQL parmi ses 100+ résultats.

4
user4223622

Séparation des prédicats en fonction de la sélectivité

Séparez votre requête en conditions de jointure et où les conditions peuvent donner un indice supplémentaire à l'optimiseur. Les conditions de jointure ont une très faible sélectivité sur chaque table et une haute sélectivité sur les tuples dans le produit vectoriel théorique. Les conditions de l'instruction where ont généralement une sélectivité beaucoup plus élevée.

Dans une condition de jointure pour chaque ligne de gauche, il y a très probablement une valeur à droite (et vice versa). De telles conditions sont donc bonnes pour joindre les résultats de deux tables, mais elles n'aident pas beaucoup à éliminer les valeurs de chaque table individuelle de l'ensemble de résultats.

Les conditions de la clause where peuvent généralement être utilisées pour éliminer des lignes individuelles d'une table de l'ensemble de résultats.

Astuce pour l'optimiseur (humain!)

C'est donc une bonne stratégie pour exécuter d'abord les conditions where sur les tables individuelles et éliminer autant de lignes que possible de l'ensemble de résultats. Après cela, on peut utiliser les conditions de jointure pour combiner les lignes survivantes.

Il n'est pas clair si l'optimiseur Oracle utilise vraiment la position de la condition dans l'instruction SQL comme indice pour optimiser la requête. Je suppose qu'il s'intéresse davantage aux faits réels dans les statistiques du tableau (il y a eu un certain changement dans la façon dont Oracle gère les différentes jointures dans 11g R1, voir ce message de l'équipe d'optimiseur Oracle pour plus de détails).

Au moins pour moi en tant qu'humain, il est très utile de savoir si une déclaration a une sélectivité sur une table unique lorsque j'essaie de comprendre et d'optimiser une requête. Vous devez également tenir compte de cela lorsque vous souhaitez placer plusieurs conditions dans une clause ON (par exemple ON (a.x=b.x AND a.y=b.y) vs mettre une des conditions dans le cas où: Vérifiez simplement la sélectivité de la condition.

Conclusion

Pour les requêtes existantes, conservez la syntaxe telle quelle. Lorsque vous créez une nouvelle requête ou refactorisez une requête existante, essayez de trier les prédicats sur la sélectivité en utilisant la syntaxe "JOIN ON": Si elle n'est pas très sélectionnable sur une seule table, placez-la dans la partie ON, sinon dans la partie WHERE.

4
stefan.schwetschke

Le signe (+) utilisé dans les jointures externes est la syntaxe Oracle pour les jointures externes

D'après les informations recueillies auprès de sources Oracle fiables, je pouvais voir que vous pouvez conserver la syntaxe de jointure externe Oracle (+) pour les packages existants car il existe plus de 200 packages et qu'Oracle les convertit toujours en interne de la syntaxe ANSI en syntaxe Oracle.

Veuillez utiliser la syntaxe ANSI à l'avenir là où il y a des limitations pour utiliser l'opérateur (+)

Veuillez trouver les liens pour une explication détaillée sur le signe (+) Jointures externes qui pourrait vous aider à décider de votre migration

syntaxe Oracle Outer Join et syntaxe ANSI

Limites de l'utilisation (+) des jointures externes

Plus d'informations sur la jointure externe Oracle

(+) Opérateur de jointure externe recommandé dans Java lors de l'utilisation des pilotes Oracle JDBC

3
psaraj12

Certains commentateurs ont déclaré que la syntaxe (+) ne permet pas les jointures externes complètes. C'est le cas, donc ce n'est pas le problème: (LEFT OUTER JOIN) UNION ALL (RIGHT OUTER JOIN).

D'autres ont dit que la performance était la raison de la transition. C'est un tas de BS, en particulier en SQL. Bien sûr, il existe quelques directives, mais chaque requête et chaque base de données a ses propres particularités, vous devez régler pour des situations spécifiques et non générales.

Les raisons de passer de (+), en plus de ne pas être standard, sont ses limites par opposition à la nouvelle syntaxe explicite: http://docs.Oracle.com/cd/E16655_01/server.121/e17209/queries006 .htm # SQLRF52354 . Commencez à lire à partir d'ici: "Oracle vous recommande d'utiliser la syntaxe FROM clause OUTER JOIN plutôt que l'opérateur de jointure Oracle."

2
itmitica

Parler de son expérience professionnelle, en utilisant JOIN plutôt que (+) est plus simple, plus rapide, plus beau et il est préférable de travailler avec la solution, spécialement lorsque vous travaillez avec des sélections de bases de données multiples (dans tous les synonymes), avec beaucoup de tables (par exemple: 40+ tables) dans une grande base de données (1000 + tableaux, certains tableaux de plus de 2 milliards de lignes), vous ressentirez une grande différence.

2
Ján Srniček

J'ai utilisé les deux approches sur différents projets et je préfère la syntaxe JOIN.

  • Il existe une séparation claire pour les conditions de jointure dans la clause ON et les conditions de filtre dans la clause WHERE.
  • Il est plus facile de lire et de gérer des requêtes volumineuses avec beaucoup de jointures.
2
Nazarii Bardiuk