web-dev-qa-db-fra.com

Différence entre la notation plus (+) d'Oracle et la notation JOIN ansi?

Quelle est la différence entre l'utilisation de la notation plus d'Oracle (+) sur la norme ansi join notation?

Y a-t-il une différence de performances?

La notation plus est-elle déconseillée?

71
Franz See

AFAIK, la notation (+) N'est présente que pour la compatibilité ascendante car Oracle a fait ses débuts avant la mise en place de la norme ANSI pour les jointures. Il est spécifique à Oracle et vous devez éviter de l'utiliser dans le nouveau code lorsqu'une version équivalente conforme aux normes est disponible.

Il semble qu'il y ait des différences entre les deux, et la notation (+) A des restrictions que la syntaxe de jointure ANSI n'a pas. Oracle recommande lui-même de ne pas utiliser la notation (+). Description complète ici dans le Oracle® Database SQL Language Reference 11g Release 1 (11.1) :

Oracle vous recommande d'utiliser la syntaxe FROM clause OUTER JOIN Plutôt que l'opérateur de jointure Oracle. Les requêtes de jointure externe qui utilisent l'opérateur de jointure Oracle (+) Sont soumises aux règles et restrictions suivantes, qui ne s'appliquent pas à la syntaxe FROM clause OUTER JOIN:

  • Vous ne pouvez pas spécifier l'opérateur (+) Dans un bloc de requête qui contient également la syntaxe de jointure de clause FROM.
  • L'opérateur (+) Ne peut apparaître que dans la clause WHERE ou, dans le contexte de la corrélation gauche (lors de la spécification de la clause TABLE) dans la clause FROM et ne peut être appliqué qu'à une colonne d'une table ou d'une vue.
  • Si A et B sont joints par plusieurs conditions de jointure, vous devez utiliser l'opérateur (+) Dans toutes ces conditions. Si vous ne le faites pas, Oracle Database renverra uniquement les lignes résultant d'une simple jointure, mais sans avertissement ni erreur pour vous informer que vous n'avez pas les résultats d'une jointure externe.
  • L'opérateur (+) Ne produit pas de jointure externe si vous spécifiez une table dans la requête externe et l'autre table dans une requête interne.
  • Vous ne pouvez pas utiliser l'opérateur (+) Pour joindre une table à lui-même, bien que les auto-jointures soient valides.

Par exemple, l'instruction suivante n'est pas valide:

SELECT employee_id, manager_id
FROM employees
WHERE employees.manager_id(+) = employees.employee_id;

Cependant, l'auto-jointure suivante est valide:

SELECT e1.employee_id, e1.manager_id, e2.employee_id
FROM employees e1, employees e2
WHERE e1.manager_id(+) = e2.employee_id;
  • L'opérateur (+) Ne peut être appliqué qu'à une colonne, pas à une expression arbitraire. Cependant, une expression arbitraire peut contenir une ou plusieurs colonnes marquées avec l'opérateur (+).
  • Une condition WHERE contenant l'opérateur (+) Ne peut pas être combinée avec une autre condition à l'aide de l'opérateur logique OR.
  • Une condition WHERE ne peut pas utiliser la condition de comparaison IN pour comparer une colonne marquée avec l'opérateur (+) Avec une expression.

Si la clause WHERE contient une condition qui compare une colonne du tableau B avec une constante, l'opérateur (+) Doit être appliqué à la colonne pour qu'Oracle renvoie les lignes du tableau A pour lesquelles il a généré des valeurs nulles pour cette colonne. Sinon, Oracle ne renvoie que les résultats d'une simple jointure.

Dans une requête qui effectue des jointures externes de plus de deux paires de tables, une seule table peut être la table générée par null pour une seule autre table. Pour cette raison, vous ne pouvez pas appliquer l'opérateur (+) Aux colonnes de B dans la condition de jointure pour A et B et la condition de jointure pour B et C. Reportez-vous à SELECT pour la syntaxe d'un élément externe joindre.

97
nagul

Je suis d'accord avec la réponse de Tony Miller et je voudrais ajouter qu'il y a aussi quelques choses que vous ne pouvez PAS faire avec le synthax (+):

  • Vous ne pouvez pas FULL OUTER JOIN deux tables, vous devez le faire manuellement avec UNION TOUS les deux jointures,
  • Vous ne pouvez pas JOINDRE EXTÉRIEUR une table à deux tables ou plus, vous devez créer manuellement une sous-requête (c'est-à-dire: b.id = a.id (+) AND c.id = a.id (+) n'est pas une clause acceptable)
12
Vincent Malgrat

La notation est toujours prise en charge à partir d'Oracle 10 (et je crois 11). Son utilisation est considérée comme "à l'ancienne" et n'est pas aussi portable que la syntaxe ANSI JOIN. Il est également considéré comme beaucoup moins lisible, bien que si vous venez du fond +, vous habituer à ANSI JOIN peut prendre un peu de temps. La chose importante à savoir avant de lancer des brickbats chez Oracle est qu'ils ont développé leur + syntaxe avant que le comité ANSI ait terminé les définitions des jointures.

Il n'y a aucune différence de performances; ils expriment la même chose.

Edit: Par "pas aussi portable" j'aurais dû dire "uniquement pris en charge dans Oracle SQL"

12
Tony Miller

La réponse la plus complète est évidemment celle de nagul .

Un ajout pour ceux qui recherchent une traduction/mappage rapide vers la syntaxe ANSI:

--
-- INNER JOIN
--
SELECT *
FROM EMP e
INNER JOIN DEPT d ON d.DEPTNO = e.DEPTNO;

 -- Synonym in deprecated Oracle (+) syntax
SELECT *
FROM EMP e,
     DEPT d
WHERE d.DEPTNO = e.DEPTNO;

--
-- LEFT OUTER JOIN
--
SELECT *
FROM EMP e
LEFT JOIN DEPT d ON d.DEPTNO = e.DEPTNO;

 -- Synonym in deprecated Oracle (+) syntax
SELECT *
FROM EMP e,
     DEPT d
WHERE d.DEPTNO (+) = e.DEPTNO;

--
-- RIGHT OUTER JOIN
--
SELECT *
FROM EMP e
RIGHT JOIN DEPT d ON d.DEPTNO = e.DEPTNO;

-- Synonym in deprecated Oracle (+) syntax
SELECT *
FROM EMP e,
     DEPT d
WHERE d.DEPTNO = e.DEPTNO(+);

--
-- CROSS JOIN
--
SELECT *
FROM EMP e
CROSS JOIN DEPT d;

 -- Synonym in deprecated Oracle (+) syntax
SELECT *
FROM EMP e,
     DEPT d;

--
-- FULL JOIN
--
SELECT *
FROM EMP e
FULL JOIN DEPT d ON d.DEPTNO = e.DEPTNO;

-- Synonym in deprecated Oracle (+) syntax !NOT WORKING!
SELECT *
FROM EMP e,
     DEPT d
WHERE d.DEPTNO (+) = e.DEPTNO(+);
11
schnatterer

L'une des bonnes raisons d'utiliser la syntaxe [~ # ~] ansi [~ # ~] sur l'ancienne Oracle La syntaxe de jointure est qu'il n'y a aucune chance de créer accidentellement un produit cartésien . Avec un plus grand nombre de tables, il y a une chance de manquer une jointure implicite avec l'ancienne syntaxe de jointure Oracle, cependant, avec la syntaxe ANSI, vous ne pouvez manquer aucune jointure car vous devez explicitement les mentionner.

Différence entre la syntaxe de jointure externe Oracle et la syntaxe ANSI/ISO .

JOINTURE EXTÉRIEURE GAUCHE -

SELECT e.last_name,
  d.department_name
FROM employees e,
  departments d
WHERE e.department_id = d.department_id(+);

SELECT e.last_name,
  d.department_name
FROM employees e
LEFT OUTER JOIN departments d
ON (e.department_id = d.department_id);

JOINTURE EXTERNE DROITE -

SELECT e.last_name,
  d.department_name
FROM employees e,
  departments d
WHERE e.department_id(+) = d.department_id;

SELECT e.last_name,
  d.department_name
FROM employees e
RIGHT OUTER JOIN departments d
ON (e.department_id = d.department_id);

JOINTURE EXTÉRIEURE COMPLÈTE -

Avant le support natif du hash fulljoint1 dans 11gR1, Oracle convertirait en interne le FULL OUTER JOIN de la manière suivante -

SELECT e.last_name,
  d.department_name
FROM employees e,
  departments d
WHERE e.department_id = d.department_id(+)
UNION ALL
SELECT NULL,
  d.department_name
FROM departments d
WHERE NOT EXISTS
  (SELECT 1 FROM employees e WHERE e.department_id = d.department_id
  );

SELECT e.last_name,
  d.department_name
FROM employees e
FULL OUTER JOIN departments d
ON (e.department_id = d.department_id);

Jetez un oeil à this .

2
Lalit Kumar B

J'utilise la notation (+), car presque toutes les requêtes liées à Oracle Apps r12 sont basées sur cela. Je n'ai pas vu une seule requête SQL avec une expression "join" standard dans les requêtes Oracle APPS (même celles fournies par Oracle lui-même). Si vous ne me croyez pas, recherchez simplement les informations liées aux applications Oracle sur Google. Par exemple: requêtes liées aux immobilisations

1
Ahmedov

notation Oracle (+) est uniquement utilisé dans Oracle, qui est spécifique au fournisseur. Et, notation de jointure standard ANSI peut être tilisé dans n'importe quel SGBDR (comme Sql Server, MySql etc.). Sinon, il n'y a aucune différence entre la notation Oracle (+) et la notation Join standard ANSI.

Si vous utilisez la notation de jointure standard ANSI dans votre requête SQL, vous pouvez utiliser la même requête dans n'importe quel SGBDR. Et, si vous êtes portage votre base de données d'Oracle vers tout autre SGBDR dans cette condition, vous devez tiliser la syntaxe ANSI.

1
abhishek
  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.
1
SriniV