web-dev-qa-db-fra.com

Pourquoi la norme SQL ANSI-92 n'est-elle pas mieux adoptée que ANSI-89?

Dans chaque entreprise où j'ai travaillé, j'ai constaté que les gens écrivaient toujours leurs requêtes SQL dans la norme ANSI-89:

select a.id, b.id, b.address_1
from person a, address b
where a.id = b.id

plutôt que la norme ANSI-92:

select a.id, b.id, b.address_1
from person a
inner join address b
on a.id = b.id

Pour une requête extrêmement simple comme celle-ci, il n'y a pas de grande différence de lisibilité, mais pour les requêtes volumineuses, je trouve que le fait de regrouper mes critères de jointure avec la liste du tableau permet de voir plus facilement où je pourrais rencontrer des problèmes dans ma jointure, et laissez-moi garder tout mon filtrage dans ma clause WHERE. Sans oublier que je pense que les jointures externes sont beaucoup plus intuitives que la syntaxe (+) dans Oracle.

Alors que j'essaie d'évangéliser ANSI-92 auprès des gens, y a-t-il des avantages concrets en termes de performances à utiliser ANSI-92 par rapport à ANSI-89? Je l'essayerais moi-même, mais les configurations Oracle que nous avons ici ne nous permettent pas d'utiliser EXPLAIN PLAN - ne voudriez pas que les gens essaient d'optimiser leur code, n'est-ce pas?

104
Patrick Harrington

Selon "SQL Performance Tuning" de Peter Gulutzan et Trudy Pelzer, parmi les six ou huit marques de SGBDR qu'ils ont testées, il n'y avait aucune différence dans l'optimisation ou les performances de SQL-89 par rapport aux jointures de style SQL-92. On peut supposer que la plupart des moteurs SGBDR transforment la syntaxe en une représentation interne avant d'optimiser ou d'exécuter la requête, de sorte que la syntaxe lisible par l'homme ne fait aucune différence.

J'essaie également d'évangéliser la syntaxe SQL-92. Seize ans après son approbation, il est grand temps que les gens commencent à l'utiliser! Et toutes les marques de base de données SQL le prennent désormais en charge, il n'y a donc aucune raison de continuer à utiliser l'abhorrent (+) Syntaxe Oracle ou *= Syntaxe Microsoft/Sybase.

Quant à savoir pourquoi il est si difficile de briser la communauté des développeurs de l'habitude SQL-89, je ne peux que supposer qu'il existe une grande "base de la pyramide" de programmeurs qui codent par copier-coller, en utilisant des exemples anciens de livres, d'articles de magazine, ou une autre base de code, et ces personnes n'apprennent pas la nouvelle syntaxe de manière abstraite. Certaines personnes s'associent à des motifs et d'autres apprennent par cœur.

Cependant, je vois progressivement des gens utiliser la syntaxe SQL-92 plus fréquemment qu'auparavant. Je réponds aux questions SQL en ligne depuis 1994.

75
Bill Karwin

Eh bien, la norme ANSI092 inclut une syntaxe assez odieuse. Natural Joins sont un et la clause USING en est un autre. À mon humble avis, l'ajout d'une colonne à une table ne devrait pas casser le code, mais un NATURAL JOIN se casse de la manière la plus flagrante. La "meilleure" façon de rompre est l'erreur de compilation. Par exemple, si vous sélectionnez * quelque part, l'ajout d'une colonne peut échouer lors de la compilation. La deuxième meilleure façon d'échouer serait une erreur d'exécution. C'est pire parce que vos utilisateurs peuvent le voir, mais cela vous donne toujours un joli avertissement que vous avez cassé quelque chose. Si vous utilisez ANSI92 et écrivez des requêtes avec des jointures NATURELLES, il ne se cassera pas au moment de la compilation et ne se cassera pas au moment de l'exécution, la requête commencera soudainement à produire des résultats erronés. Ces types de bogues sont insidieux. Les rapports vont mal, la divulgation financière potentielle est incorrecte.

Pour ceux qui ne connaissent pas les jointures naturelles. Ils joignent deux tables sur chaque nom de colonne qui existe dans les deux tables. Ce qui est vraiment cool quand vous avez une clé à 4 colonnes et que vous en avez marre de la taper. Le problème survient lorsque Table1 a une colonne préexistante nommée DESCRIPTION et que vous ajoutez une nouvelle colonne à Table2 nommée, oh je ne sais pas, quelque chose d'inoffensif comme, mmm, DESCRIPTION et maintenant vous joignez les deux tables sur un VARCHAR2 (1000) champ de forme libre.

La clause USING peut conduire à une ambiguïté totale en plus du problème décrit ci-dessus. Dans un autre SO post , quelqu'un a montré ce SQL ANSI-92 et a demandé de l'aide pour le lire.

SELECT c.* 
FROM companies AS c 
JOIN users AS u USING(companyid) 
JOIN jobs AS j USING(userid) 
JOIN useraccounts AS us USING(userid) 
WHERE j.jobid = 123

C'est complètement ambigu. J'ai mis une colonne UserID à la fois dans les entreprises et les tables d'utilisateurs et il n'y a aucune plainte. Que faire si la colonne UserID dans les entreprises est l'ID de la dernière personne à modifier cette ligne?

Je suis sérieux, quelqu'un peut-il expliquer pourquoi une telle ambiguïté était nécessaire? Pourquoi est-il intégré directement dans la norme?

Je pense que Bill a raison de dire qu'il existe une grande base de développeurs qui copient/collent là-bas grâce au codage. En fait, je peux admettre que je suis du genre en ce qui concerne ANSI-92. Chaque exemple que j'ai jamais vu montrait plusieurs jointures imbriquées entre parenthèses. Honnêteté, cela rend difficile au mieux le choix des tables dans le sql. Mais un évangiliste SQL92 a expliqué que cela forcerait en fait un ordre de jointure. JESUS ​​... tous ces pasteurs de copie que j'ai vus forcent désormais un ordre de jointure - un travail qui est 95% du temps préférable de laisser aux optimiseurs surtout un copieur/copieur.

Tomalak a bien compris quand il a dit:

les gens ne passent pas à une nouvelle syntaxe juste parce qu'elle est là

Cela doit me donner quelque chose et je ne vois aucun avantage. Et s'il y a un avantage, les négatifs sont un albatros trop gros pour être ignoré.

16
Mark Brady

Quelques raisons me viennent à l'esprit:

  • les gens le font par habitude
  • les gens sont paresseux et préfèrent les jointures "à l'ancienne" car elles impliquent moins de frappe
  • les débutants ont souvent du mal à comprendre la syntaxe de jointure SQL-92
  • les gens ne passent pas à une nouvelle syntaxe juste parce qu'elle est là
  • les gens ne sont pas conscients des avantages de la nouvelle syntaxe (si vous voulez l'appeler ainsi), principalement qu'elle vous permet de filtrer une table avant vous effectuez une jointure externe, et non après elle quand tout ce que vous avoir est la clause WHERE.

Pour ma part, je fais toutes mes jointures dans la syntaxe SQL-92, et je convertis le code où je peux. C'est le moyen le plus propre, le plus lisible et le plus puissant de le faire. Mais il est difficile de convaincre quelqu'un d'utiliser le nouveau style, quand il pense que cela lui fait du mal en termes de travail de frappe sans changer le résultat de la requête.

14
Tomalak

En réponse au message NATURAL JOIN and USING ci-dessus.

POURQUOI verriez-vous jamais la nécessité de les utiliser - ils n'étaient pas disponibles dans ANSI-89 et ont été ajoutés pour ANSI-92 comme ce que je ne vois que comme raccourci.

Je ne laisserais jamais une jointure au hasard et spécifierais toujours la table/l'alias et l'id.

Pour moi, la seule voie à suivre est ANSI-92. Il est plus verbeux et la syntaxe n'est pas appréciée par les adeptes de l'ANSI-89 mais il sépare soigneusement vos JOINS de votre FILTRAGE.

10
Roger Bold

Permettez-moi d'abord de dire que dans SQL Server, la syntaxe de jointure externe (* =) ne donne pas toujours des résultats corrects. Il y a des moments où il interprète cela comme une jointure croisée et non comme une jointure externe. Il y a donc une bonne raison d'arrêter de l'utiliser. Et cette syntaxe de jointure externe est une fonctionnalité obsolète et ne figurera pas dans la prochaine version de SQL Server après SQL Server 2008. Vous pourrez toujours effectuer les jointures internes, mais pourquoi diable voudrait-on le faire? Ils ne sont pas clairs et sont beaucoup plus difficiles à maintenir. Vous ne savez pas facilement ce qui fait partie de la jointure et ce qui est vraiment juste la clause where.

Une raison pour laquelle je pense que vous ne devriez pas utiliser l'ancienne syntaxe est que la compréhension des jointures et de ce qu'elles font et ne font pas est une étape critique pour quiconque écrira du code SQL. Vous ne devez pas écrire de code SQL sans bien comprendre les jointures. Si vous les comprenez bien, vous arriverez probablement à la conclusion que la syntaxe ANSI-92 est plus claire et plus facile à maintenir. Je n'ai jamais rencontré un expert SQL qui n'utilisait pas la syntaxe ANSI-92 de préférence à l'ancienne syntaxe.

La plupart des personnes que j'ai rencontrées ou traitées qui utilisent l'ancien code ne comprennent vraiment pas les jointures et ont donc des problèmes lors de l'interrogation de la base de données. C'est mon expérience personnelle, donc je ne dis pas que c'est toujours vrai. Mais en tant que spécialiste des données, j'ai dû réparer trop de ces ordures au fil des ans pour ne pas y croire.

5
HLGEM

J'ai appris l'ANSI-89 à l'école et travaillé dans l'industrie pendant quelques années. Puis j'ai quitté le fabuleux monde du SGBD pendant 8 ans. Mais ensuite je suis revenu et ce nouveau truc ANSI 92 a été enseigné. J'ai appris la syntaxe Join On et maintenant j'enseigne réellement SQL et je recommande la nouvelle syntaxe JOIN ON.

Mais l'inconvénient que je vois est que les sous-requêtes corrélées ne semblent pas avoir de sens à la lumière des jointures ANSI 92. Lorsque les informations de jointure étaient incluses dans le WHERE et que les sous-requêtes corrélées sont "jointes" dans le WHERE, tout semblait correct et cohérent. Dans ANSI 92, les critères de jointure de table ne sont pas dans WHERE et la sous-requête "join" est, la syntaxe semble incohérente. D'un autre côté, essayer de "corriger" cette incohérence ne ferait probablement qu'aggraver la situation.

4
Scot McDermid

Inertie et praticité.

ANSI-92 SQL est comme la saisie tactile. D'une certaine manière théorique, cela pourrait tout améliorer un jour, mais je peux taper beaucoup plus rapidement en regardant les touches avec quatre doigts maintenant. Il faudrait que je recule pour avancer, sans aucune garantie qu'il y aura un jour un gain.

L'écriture SQL représente environ 10% de mon travail. Si j'ai besoin d'ANSI-92 SQL pour résoudre un problème que ANSI-89 SQL ne peut pas résoudre, je l'utilise. (Je l'utilise dans Access, en fait.) Si l'utiliser tout le temps m'aiderait à résoudre mes problèmes existants beaucoup plus rapidement, je passerais le temps à l'assimiler. Mais je peux éliminer SQL ANSI-89 sans jamais penser à la syntaxe. Je suis payé pour résoudre des problèmes - penser à la syntaxe SQL est une perte de temps et d'argent pour mon employeur.

Un jour, jeune Grasshopper, vous défendrez votre utilisation de la syntaxe SQL ANSI-92 contre les jeunes qui se plaignent que vous devriez utiliser SQL3 (ou autre). Et puis vous comprendrez. :-)

2
JPLemme

J'ai eu une requête qui a été écrite à l'origine pour SQL Server 6.5, qui ne prend pas en charge la syntaxe de jointure SQL 92, c'est-à-dire.

select foo.baz
from foo
  left outer join bar
  on foo.a = bar.a

a été écrit à la place comme

select foo.baz
from foo, bar
where foo.a *= bar.a

La requête existait depuis un certain temps et les données pertinentes s'étaient accumulées pour ralentir l'exécution de la requête, au bout d'environ 90 secondes. Au moment où ce problème est survenu, nous avions mis à niveau vers SQL Server 7.

Après avoir déblayé les index et autres modifications de Pâques, j'ai changé la syntaxe de jointure pour être conforme à SQL 92. Le temps de requête est tombé à 3 secondes.

Il y a une bonne raison de changer.

Republié de ici .

2
Dave

Je ne connais pas la réponse à coup sûr .. c'est une guerre de religion (albiet d'un moindre degré que Mac-Pc ou autres)

On peut supposer que, jusqu'à une date assez récente, Oracle (et peut-être d'autres fournisseurs également) n'adoptaient pas la norme ANSI-92 (je pense que c'était dans Oracle v9, ou à peu près) et donc, pour les développeurs DBA/Db travaillant dans des entreprises qui utilisaient toujours ces versions, (ou voulaient que le code soit portable sur les serveurs qui pourraient utiliser ces versions, ils devaient s'en tenir à l'ancien standard ...

C'est vraiment dommage, car la nouvelle syntaxe de jointure est beaucoup plus lisible et l'ancienne syntaxe génère des résultats incorrects (incorrects) dans plusieurs scénarios bien documentés.

  • Plus précisément, les jointures externes lorsqu'il existe des prédicats de filtrage conditionnel sur les colonnes non liées à la jointure de la table du côté "externe" de la jointure.
2
Charles Bretana

Je ne peux pas parler pour toutes les écoles mais dans mon université quand nous faisions le module SQL de notre cours, ils n'enseignaient pas ANSI-92, ils enseignaient ANSI-89 - sur un vieux système VAX à ça! Je n'ai pas été exposé à ANSI-92 jusqu'à ce que je commence à fouiller dans Access après avoir créé des requêtes à l'aide du concepteur de requêtes, puis à creuser dans le code SQL. Réalisant que je n'avais aucune idée de la façon dont il terminait les jointures, ni des implications de la syntaxe, j'ai commencé à creuser plus profondément pour pouvoir le comprendre.

Étant donné que la documentation disponible n'est pas exactement intuitive dans beaucoup de cas, et que les gens ont tendance à s'en tenir à ce qu'ils savent et dans de nombreux cas ne s'efforcent pas d'en apprendre plus que ce dont ils ont besoin pour faire leur travail, c'est il est facile de comprendre pourquoi l'adoption prend autant de temps.

Bien sûr, il y a ces évangélistes techniques qui aiment bricoler et comprendre et ce sont généralement ces types qui adoptent les principes "les plus récents" et tentent de convertir le reste.

Curieusement, il me semble que beaucoup de programmeurs sortent de l'école et arrêtent d'avancer; pensant que parce que c'est ce qu'on leur a enseigné, c'est ainsi que cela se fait. Ce n'est que lorsque vous enlevez vos œillères que vous réalisez que l'école était uniquement destinée à vous enseigner les bases et à vous donner suffisamment de compréhension pour apprendre le reste vous-même et que vous avez à peine effleuré la surface de ce qu'il y a à savoir; maintenant c'est à vous de continuer sur cette voie.

Bien sûr, c'est juste mon opinion basée sur mon expérience.

1
BenAlabaster

Voici quelques points comparant SQL-89 et SQL-92 et clarifiant certaines idées fausses dans d'autres réponses.

  1. NATURAL JOINS sont une horrible idée. Ils sont implicites et nécessitent des méta-informations sur la table. Rien sur SQL-92 ne nécessite leur utilisation, il suffit donc de les ignorer . Ils ne sont pas pertinents pour cette discussion.
  2. USING est une excellente idée, elle a deux effets:
    1. Il ne produit qu'une seule colonne sur l'ensemble de résultats à partir d'une équijoin.
    2. Il applique une convention saine et saine. Dans SQL-89, des personnes écrivaient la colonne id sur les deux tables. Après avoir rejoint les tables, cela devient ambigu et nécessite un alias explicite. De plus, les id sur la jointure avaient presque certainement des données différentes. Si vous associez une personne à une entreprise, vous devez maintenant alias un id à person_id et un id à company_id, sans lequel la jointure produirait deux colonnes ambiguës. L'utilisation d'un identificateur global unique pour la clé de substitution de la table est la convention que la récompense standard avec USING.
  3. La syntaxe SQL-89 est une implicite CROSS JOIN. UNE CROSS JOIN ne réduit pas l'ensemble, il l'agrandit implicitement. FROM T1,T2 est le même que FROM T1 CROSS JOIN T2, qui produit une jointure cartésienne qui n'est généralement pas ce que vous voulez. Avoir la sélectivité pour réduire cette suppression à une condition WHERE éloignée signifie que vous êtes plus susceptible de faire des erreurs lors de la conception.
  4. SQL-89 , et SQL-92 explicites JOIN ont une priorité différente. JOIN a une priorité plus élevée. Pire encore, certaines bases de données comme MySQL se sont trompées pendant très longtemps. . Mélanger les deux styles est donc une mauvaise idée, et le style beaucoup plus populaire aujourd'hui est le style SQL-92.
1
Evan Carroll

Raisons pour lesquelles les gens utilisent ANSI-89 à partir de mon expérience pratique avec des programmeurs, des stagiaires et des nouveaux diplômés, jeunes et vieux:

  • Ils apprennent SQL à partir du code existant qu'ils voient (plutôt que des livres) et apprennent ANSI-89 à partir du code
  • ANSI-89 car est moins de frappe
  • Ils n'y pensent pas et utilisent l'un ou l'autre style et ne savent même pas lequel des deux est considéré comme nouveau ou ancien et ne s'en soucient pas non plus
  • L'idée que le code est également une communication avec le prochain programmeur qui vient à jour pour maintenir le code n'existe pas. Ils pensent qu'ils parlent à l'ordinateur et l'ordinateur s'en fiche.
  • L'art du "codage propre" est inconnu
  • La connaissance du langage de programmation et de SQL en particulier est si faible qu'ils copient et collent ensemble ce qu'ils trouvent ailleurs
  • Préférence personnelle

Personnellement, je préfère ANSI-92 et modifie chaque requête que je vois dans la syntaxe ANSI-89 parfois uniquement pour mieux comprendre la déclaration SQL à portée de main. Mais j'ai réalisé que la majorité des personnes avec lesquelles je travaille ne sont pas suffisamment qualifiées pour écrire des jointures sur de nombreuses tables. Ils codent aussi bien qu'ils le peuvent et utilisent ce qu'ils ont mémorisé la première fois qu'ils ont rencontré une instruction SQL.

1
hol

1) Manière standard d'écrire OUTER JOIN, contre * = ou (+) =

2) JOINTURE NATURELLE

3) Selon le moteur de base de données, les tendances ANSI-92 seront plus optimales.

4) Optimisation manuelle:

Disons que nous avons la prochaine syntaxe (ANSI-89):

(1)select * from TABLE_OFFICES to,BIG_TABLE_USERS btu
where to.iduser=tbu.iduser and to.idoffice=1

Il pourrait être écrit comme suit:

(2)select * from TABLE_OFFICES to
inner join BIG_TABLE_USERS btu on to.iduser=tbu.iduser
where to.idoffice=1

Mais aussi comme:

(3)select * from TABLE_OFFICES to
inner join BIG_TABLE_USERS btu on to.iduser=tbu.iduser and to.idoffice=1

Tous (1), (2), (3) renvoient le même résultat, mais ils sont optimisés différemment, cela dépend du moteur de base de données mais la plupart le font:

  • (1) c'est au moteur de base de données de décider de l'optimisation.
  • (2) il joint les deux tables puis effectue le filtrage par bureau.
  • (3) il filtre les BIG_TABLE_USERS en utilisant l'idoffice puis joint les deux tables.

5) Les requêtes plus longues sont moins compliquées.

1
magallanes

Je peux répondre du point de vue d'un développeur moyen, connaissant juste assez de SQL pour comprendre les deux syntaxes, mais toujours googler la syntaxe exacte d'insertion chaque fois que j'en ai besoin ... :-P (je ne fais pas SQL toute la journée , juste en corrigeant de temps en temps certains problèmes.)

Eh bien, en fait, je trouve la première forme plus intuitive, ne faisant aucune hiérarchie apparente entre les deux tables. Le fait que j'aie appris SQL avec des livres peut-être anciens, montrant le premier formulaire, n'aide probablement pas ... ;-)
Et la première référence que je trouve sur une recherche sql select dans Google (qui renvoie principalement des réponses en français pour moi ...) montre d'abord l'ancien formulaire (puis explique le second).

Juste donner quelques conseils sur la question "pourquoi" ... ^ _ ^ Je devrais lire un bon livre moderne (DB agnostique) sur le sujet. Si quelqu'un a des suggestions ...

1
PhiLho

Une nouvelle norme SQL hérite de tout de la norme précédente, alias `` les entraves de la compatibilité ''. Ainsi, le style de jointure "ancien"/"séparé par des virgules"/"non qualifié" est une syntaxe SQL-92 parfaitement valide.

Maintenant, je soutiens que le SQL-92 NATURAL JOIN est la seule jointure dont vous avez besoin. Par exemple, je soutiens qu'il est supérieur à inner join car il ne génère pas de colonnes en double - plus de variables de plage dans les clauses SELECT pour lever l'ambiguïté des colonnes! Mais je ne peux pas m'attendre à changer tous les cœurs et tous les esprits, je dois donc travailler avec des codeurs qui continueront à adopter ce que je considère personnellement comme des styles de jointure hérités (et ils peuvent même se référer aux variables de plage comme des `` alias ''!). C'est la nature du travail d'équipe et ne fonctionne pas en vase clos.

L'une des critiques du langage SQL est que le même résultat peut être obtenu en utilisant un certain nombre de syntaxes sémantiquement équivalentes (certaines utilisant l'algèbre relationnelle, certaines utilisant le calcul relationnel), où le choix du meilleur se résume simplement à un style personnel . Je suis donc aussi à l'aise avec les jointures "à l'ancienne" qu'avec INNER. Que je prenne le temps de les réécrire en tant que NATURAL dépend du contexte.

0
onedaywhen

Oracle n'implémente pas du tout bien ANSI-92. J'ai eu plusieurs problèmes, notamment parce que les tableaux de données d'Oracle Apps sont très bien dotés en colonnes. Si le nombre de colonnes dans vos jointures dépasse environ 1050 colonnes (ce qui est très facile à faire dans les applications), vous obtiendrez cette erreur parasite qui n'a absolument aucun sens logique:

ORA-01445: cannot select ROWID from a join view without a key-preserved table.

La réécriture de la requête pour utiliser l'ancienne syntaxe de jointure fait disparaître le problème, ce qui semble pointer du doigt la responsabilité de la mise en œuvre des jointures ANSI-92.

Jusqu'à ce que je rencontre ce problème, j'étais un promoteur inébranlable de l'ASNI-92, en raison des avantages de réduire le risque d'une jointure croisée accidentelle, ce qui est beaucoup trop facile à faire avec une syntaxe à l'ancienne.

Maintenant, cependant, j’ai beaucoup plus de mal à y insister. Ils pointent vers la mauvaise implémentation d'Oracle et disent "Nous le ferons à notre façon, merci."

0
Jonathan