Pourquoi la norme SQL ANSI-92 n'est-elle pas mieux adoptée que L'ANSI-89?
dans chaque entreprise où j'ai travaillé, j'ai constaté que les gens écrivaient encore 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 une grande différence dans la lisibilité, mais pour les grandes requêtes, je trouve que le fait d'avoir mes critères de jointure groupés avec la liste sur le tableau il est beaucoup plus facile de voir où je pourrais avoir des problèmes dans mon Rejoignez - moi, et laissez-moi garder tout mon filtrage dans ma clause où. Sans mentionner que je pense que les jointures externes sont beaucoup plus intuitives que la syntaxe (+) dans Oracle.
alors que j'essaie d'évangéliser L'ANSI-92, y a-t-il des avantages concrets à utiliser L'ANSI-92 plutôt que L'ANSI-89? Je l'essayerais bien moi - même, mais les configurations Oracle que nous avons ici ne nous permettent pas D'utiliser le plan expliquer - ne voudrait pas que les gens essaient d'optimiser leur code, n'est-ce pas?
16 réponses
selon "SQL Performance Tuning" de Peter Gulutzan et Trudy Pelzer, des six ou huit marques RDBMS testées, il n'y avait aucune différence dans l'optimisation ou la performance des joints de style SQL-89 par rapport à SQL-92. On peut supposer que la plupart des moteurs RDBMS 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 aussi d'évangéliser la syntaxe SQL-92. Seize ans après son approbation, il est temps que les gens commencent à l'utiliser! Et toutes les marques de la base de données SQL le prennent maintenant en charge, il n'y a donc aucune raison de continuer à utiliser l'odieuse syntaxe (+)
Oracle ou *=
Microsoft/Sybase.
quant à la raison pour laquelle il est si difficile de briser la communauté des développeurs de L'habitude SQL-89, Je ne peux que supposer qu'Il ya une grande "base de la pyramide" des programmeurs qui code par copier & coller, en utilisant des exemples anciens de livres, des articles de magazine, ou une autre base de code, et ces gens n'apprennent pas une nouvelle syntaxe abstraitement. Certaines personnes suivent le modèle, et d'autres apprennent par cœur.
je vois peu à peu des gens qui utilisent la syntaxe SQL-92 plus souvent que je ne le faisais, cependant. Je répondais aux questions de SQL en ligne depuis 1994.
Eh bien, la norme ANSI092 comprend une syntaxe assez odieuse. Jointures Naturelles sont l'un et l'UTILISATION de la Clause en est une autre. IMHO, l'ajout d'une colonne à une table ne devrait pas briser le code, mais une jointure naturelle se brise d'une façon très flagrante. La "meilleure" façon de rompre est par erreur de compilation. Par exemple, si vous sélectionnez * somewhere, l'ajout d'une colonne pourrait ne pas compiler. La meilleure façon d'échouer serait une erreur d'exécution. C'est pire parce que vos utilisateurs peuvent voir, mais il vous offre 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 brisera pas au moment de la compilation et il ne se brisera pas au moment de l'exécution, la requête commencera tout d'un coup à produire de mauvais résultats. Ces types de bogues sont insidieux. Les rapports se trompent, la divulgation financière est peut-être 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 touche à 4 colonnes et que vous en avez marre de la taper. Le problème vient quand la Table 1 a une colonne préexistante nommée DESCRIPTION et que vous ajoutez une nouvelle colonne à la Table 2 nommée, oh Je ne sais pas, quelque chose d'inoffensif comme, MMM, DESCRIPTION et maintenant vous rejoignez les deux tables sur un champ VARCHAR2(1000) qui est libre.
la clause D'utilisation peut entraîner 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 D'identification dans les sociétés et les tables d'utilisateurs et il n'y a pas de plainte. Que se passe-t-il 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 construit directement dans la norme?
je pense que Bill a raison de dire qu'il y a une grande base de développeurs qui copient/collent à travers le codage. En fait, je peux admettre que j'en suis un quand il s'agit de L'ANSI-92. Chaque exemple que j'ai vu montrait des jointures multiples imbriquées entre parenthèses. L'honnêteté, qui rend la sélection des tables dans le sql difficile au mieux. Mais alors un évangéliste de SQL92 a expliqué que ce serait en fait forcer un ordre de rejoindre. JÉSUS... toutes les copies que j'ai vues sont maintenant en fait, forcer une commande de jointure - un travail qui est de 95% du temps mieux laissé aux optimiseurs surtout une copie/pâte.
Tomalak a raison quand il a dit,
les gens ne passent pas à une nouvelle syntaxe parce qu'il est là
il doit me donner quelque chose et je ne vois pas d'avantage. Et s'il y a un bon côté, les négatifs sont un albatros trop grand pour être ignoré.
quelques raisons viennent à l'esprit:
- les gens le font par habitude
- les gens sont paresseux et préfèrent le" vieux style " se joint parce qu'ils impliquent moins de Dactylographie
- les débutants ont souvent leurs problèmes autour de la syntaxe de jointure SQL-92
- les gens ne changent pas de syntaxe juste parce qu'elle est là
- les gens ne sont pas au courant des avantages de la nouvelle (si vous voulez pour l'appeler que la syntaxe a), principalement qu'il vous permet de filtrer une table avant vous faites une jointure externe, et pas après quand tout ce que vous avez est la clause où.
pour ma part, je fais toutes mes jointures dans la syntaxe SQL-92, et je convertis le code où je peux. C'est le plus propre, plus lisible et puissant pour le faire. Mais il est difficile de convaincre quelqu'un d'utiliser le nouveau style, quand ils pensent que cela les blesse en termes de plus de travail de Dactylographie alors que non changer le résultat de la requête.
en réponse à la jointure naturelle et en utilisant le poteau ci-dessus.
pourquoi auriez - vous jamais vu la nécessité d'utiliser ces-ILS n'étaient pas disponibles dans ANSI-89 et ont été ajoutés pour ANSI-92 que je ne peux voir comme un raccourci.
Je ne laisserais jamais une jointure au hasard et je préciserais toujours la table/alias et l'id.
pour moi, la seule façon d'y aller est L'ANSI-92. Il est plus verbeux et la syntaxe n'est pas aimé par ANSI-89 followers mais il sépare soigneusement vos jointures de votre filtrage.
permettez-moi D'abord de dire que dans SQL Server la syntaxe de jointure externe (*=) ne donne pas des résultats corrects tout le temps. Il y a des moments où il interprète comme une jointure croisée et pas une jointure externe. Il y a donc une bonne raison d'arrêter de l'utiliser. Et que la syntaxe de jointure externe est une fonctionnalité dépréciée et ne sera pas dans la prochaine version de SQL Server après SQL Server 2008. Vous pourrez toujours faire les jointures intérieures, mais pourquoi quelqu'un voudrait-il? Ils ne sont pas clairs et beaucoup plus difficile à maintenir. Vous ne savez pas facilement ce qui fait partie de la jointure et ce qui est vraiment juste la clause où.
une des raisons pour lesquelles je pense que vous ne devriez pas utiliser l'ancienne syntaxe est que comprendre les jointures et 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 comprendre les jointures complètement. 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'utilise pas la syntaxe ANSI-92 de préférence à l'ancienne syntaxe.
la plupart des gens que j'ai rencontré ou traité qui utilisent l'ancien code, ne comprennent vraiment pas jointures et donc avoir des problèmes lors de la recherche dans la base de données. Ceci 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 trucs au fil des ans pour ne pas y croire.
on m'a enseigné L'ANSI-89 à l'école et j'ai travaillé dans l'industrie pendant quelques années. Puis j'ai quitté le monde fabuleux des SGBD pendant 8 ans. Mais ensuite je suis revenu et ce nouveau truc ANSI 92 était enseigné. J'ai appris la jointure sur la syntaxe et maintenant j'enseigne SQL et je recommande la nouvelle jointure sur la syntaxe.
mais l'inconvénient que je vois est que les sous-séries corrélées ne semblent pas avoir de sens à la lumière des jointures ANSI 92. Quand l'information de jointure a été incluse dans le les sous-séries corrélées sont" unies " dans les domaines où tout semble juste et cohérent. Dans la table ANSI 92 join criteria n'est pas dans où 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'empirer les choses.
Je ne suis pas sûr de la réponse.. il s'agit d'une guerre religieuse (albiet d'un degré moindre que Mac-Pc ou d'autres)
une supposition est que jusqu'à assez récemment, Oracle, (et peut-être d'autres fournisseurs ainsi) n'a pas adopté la norme ANSI-92 (je pense qu'il était dans Oracle v9, ou à peu près) et donc, pour les développeurs DBAs/Db travaillant dans les entreprises qui utilisaient encore ces versions, (ou voulait code pour être portable à travers les serveurs qui pourraient utiliser ces versions, ils ont dû tenir à l'ancienne norme...
c'est vraiment dommage, car la nouvelle syntaxe join est beaucoup plus lisible, et l'ancienne syntaxe génère des résultats erronés (incorrects) dans plusieurs scénarios bien documentés.
- plus précisément, les jointures extérieures lorsqu'il y a sont des prédicats de filtrage conditionnel sur les colonnes non-jointives liées de la tableau sur "l'extérieur" du côté de la rejoindre.
inertie et praticité.
ANSI-92 SQL, c'est comme taper à la machine. En théorie, ça pourrait tout arranger un jour, mais je peux taper plus vite en regardant les clés avec quatre doigts maintenant. J'aurais besoin d'aller en arrière pour aller de l'avant, sans aucune garantie qu'il y aurait jamais un paiement.
écrire SQL est 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, alors je l'utiliserai. (Je l'utiliser dans l'Accès, en fait.) Si vous utilisez tout le temps de m'aider à résoudre mes problèmes beaucoup plus rapidement, je passerais le temps de l'assimiler. Mais je peux sortir ANSI-89 SQL 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 de mon employeur.
un jour, Jeune Sauterelle, vous défendrez votre utilisation de la syntaxe ANSI-92 SQL contre les jeunes qui pleurnichent que vous devriez utiliser SQL3 (ou quoi.) Et puis vous allez comprendre. :- )
j'ai eu une requête qui a été écrite à l'origine pour SQL Server 6.5, qui ne supportait pas la syntaxe SQL 92 join, i.e.
select foo.baz
from foo
left outer join bar
on foo.a = bar.a
a plutôt été écrit comme
select foo.baz
from foo, bar
where foo.a *= bar.a
la requête avait été autour pendant un certain temps, et les données pertinentes s'étaient accumulées pour faire courir la requête trop lente, approximativement 90 secondes pour compléter. Au moment où ce problème est apparu, nous avions mis à niveau vers SQL Server 7.
après avoir gloussé avec des index et d'autres Easter-egging, j'ai changé la syntaxe de jointure pour être compatible SQL 92. Le temps de requête est tombé à 3 secondes.
il y a une bonne raison de changer.
repris de ici .
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'insert chaque fois que j'en ai besoin... :-P (je ne fais pas de SQL toute la journée, juste la correction de certains problèmes de temps à autre.)
en fait, je trouve la première forme plus intuitive, ne faisant aucune hiérarchie apparente entre les deux tables. Le fait que J'ai appris SQL avec peut-être de vieux livres, montrant la première forme, ne aider... ;- )
Et la première référence que je trouve sur une sql sélectionner recherche dans Google (qui renvoie la plupart des réponses en français pour moi...) montre d'abord la plus ancienne forme (alors expliquer la seconde).
donne juste quelques indices sur la question" pourquoi"... ^ _ _ _ Je devrais lire un bon livre moderne (DB agnostic) sur le sujet. Si quelqu'un a des suggestions...
Je ne peux pas parler pour toutes les écoles mais à 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 à cela! Je n'ai pas été exposé à L'ANSI-92 jusqu'à ce que je commence à creuser dans L'accès après avoir construit quelques requêtes en utilisant le concepteur de requête et puis creuser dans le code SQL. En me rendant compte que je n'avais aucune idée de comment il achevait les jointures, ou les implications de la syntaxe j'ai commencé à creuser plus profondément pour que je puisse 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 qu'ils n'en ont besoin pour faire leur travail, 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 il tend à être ces types qui adoptent les" nouveaux " principes et essayer de convertir reste.
bizarrement, 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 comme ça que c'est fait. Ce n'est pas avant d'avoir enlevé vos œillères que vous réalisez que l'école était seulement censée vous enseigner les bases et vous donner assez 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 votre travail de continuer ce chemin.
bien sûr, c'est juste mon opinion basée sur mon expérience.
1) Standard way to write OUTER jointure, versus * = or ( + ) =
2) JOINT NATUREL
3) dépendent dans le moteur de base de données, ANSI-92 tendances à être plus optimale.
4) optimisation manuelle:
disons que nous avons la syntaxe suivante (ANSI-89):
(1)select * from TABLE_OFFICES to,BIG_TABLE_USERS btu
where to.iduser=tbu.iduser and to.idoffice=1
pourrait s'écrire comme:
(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) retourner le même résultat, mais ils sont optimisés différemment, ça dépend du moteur de base de données, mais la plupart d'entre eux :
- (1) son moteur de base de données décider de l'optimisation.
- (2) Il joint les deux tables puis faire le filtre par bureau.
- (3) Il filtre les gros _TABLE_USERS en utilisant le bureau ID, puis rejoint les deux tables.
5) Plus les requêtes sont moins salissant.
Oracle n'implémente pas très bien ANSI-92. J'ai eu plusieurs problèmes, notamment parce que les tables de données dans les applications Oracle sont très bien dotées de colonnes. Si le nombre de colonnes dans vos jointures dépasse environ 1050 colonnes (ce qui est très facile à faire dans les applications), alors vous obtiendrez cette erreur fausse qui ne fait absolument aucun sens logique:
ORA-01445: cannot select ROWID from a join view without a key-preserved table.
Ré-écriture de la requête à utiliser l'ancien style de la syntaxe de jointure rend le problème disparaît, ce qui semble indiquer le doigt du blâme se joint carrément à la mise en œuvre de L'ANSI-92.
Jusqu'à ce que j'ai rencontré ce problème, j'étais un promoteur inébranlable D'ASNI-92, en raison des avantages de réduire la chance d'une jonction croisée accidentelle, ce qui est beaucoup trop facile à faire avec la syntaxe ancienne.
Maintenant, cependant, je trouve qu'il est beaucoup plus difficile d'insister sur ce point. Ils pointent du doigt la mauvaise implémentation D'Oracle et disent "Nous le ferons à notre façon, merci."
raisons pour lesquelles les gens utilisent ANSI-89 à partir de mon expérience pratique avec les programmeurs et les stagiaires, jeunes et vieux, et les nouveaux diplômés:
- ils apprennent le SQL à partir du code existant qu'ils voient (plutôt que des livres) et apprennent L'ANSI-89 à partir du code
- ANSI-89 parce que 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 se soucient pas non plus
- l'idée que le code est aussi une communication au prochain programmeur qui arrive en maintenant le code n'existe pas. Ils pensent qu'ils parlent à l'ordinateur et que l'ordinateur s'en fiche.
- L'art de "codage propre" est inconnu
- la connaissance du langage de programmation et de SQL en particulier est si pauvre qu'ils copient et collent ensemble ce qu'ils trouvent ailleurs
- préférence personnelle
Personnellement, je préfère ANSI-92 et je change chaque requête que je vois dans la syntaxe ANSI-89 parfois seulement pour mieux comprendre la déclaration SQL à portée de main. Mais j'ai réalisé que la majorité des gens avec qui je travaille ne sont pas assez qualifiés pour écrire se joint à de nombreuses tables. Ils codent aussi bien qu'ils peuvent et utilisent ce qu'ils ont appris la première fois qu'ils ont rencontré une déclaration SQL.
une nouvelle norme SQL hérite tout de la norme précédente, A. K. A. "les chaînes de la compatibilité". Ainsi ,le style de jointure' old ' / 'comma-separated' / 'unqualified' est parfaitement valide SQL-92 sytax.
maintenant, je soutiens que le NATURAL JOIN
de SQL-92 est la seule jointure dont vous avez besoin. Par exemple, je soutiens qu'il est supérieur à inner join
parce qu'il ne génère pas de colonnes dupliquées - plus de variables de gamme dans SELECT
clauses pour désambiguer les colonnes! Mais je ne peux pas prévu pour changer chaque cœur et esprit, donc je dois travailler avec des codeurs qui vont continuer à adopter ce que je considère personnellement être des styles de jointure legacy (et ils peuvent même se référer à des variables de gamme comme "alias"!). C'est la nature du travail d'équipe et de ne pas fonctionner 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émantiques équivalentes (certaines utilisant l'algèbre relationnelle, d'autres utilisant la syntaxe relationnelle). calculus), où le choix du "meilleur" vient tout simplement de style personnel. Je suis donc aussi à l'aise avec les "Old-style" joins que je le suis avec INNER
. Que je prenne le temps de les réécrire en NATURAL
dépend du contexte.
voici quelques points en comparant SQL-89, et SQL-92 et en dissipant quelques idées fausses dans d'autres réponses.
-
NATURAL JOINS
sont une idée horrible. Ils sont implicites et ils nécessitent des méta-informations sur la table. Rien au sujet de SQL-92 nécessite leur utilisation si simplement les ignorer . Ils ne sont pas pertinents pour cette discussion. -
USING
est une grande idée, il a deux effets:- il produit une seule colonne sur le jeu de résultats d'un equijoin.
- il applique une convention saine et saine. En SQL-89, Il y avait des gens qui écrivaient la colonne
id
sur les deux tables. Après que vous rejoignez les tables, cela devient et ambigu et il exige aliasing explicite. De plus, lesid
s sur la jointure avaient presque certainement des données différentes. Si vous rejoignez personne à entreprise, vous devez maintenant alias unid
àperson_id
, et unid
àcompany_id
, sans lequel la jointure produirait deux colonnes ambiguës. L'utilisation d'un identificateur unique à l'échelle mondiale pour la clé de substitution de la table est la convention standard rewards avecUSING
.
- la syntaxe SQL-89 est un
CROSS JOIN
implicite . UnCROSS JOIN
ne réduit pas l'ensemble, il le développe implicitement.FROM T1,T2
est le même queFROM T1 CROSS JOIN T2
, qui produit Cartésien de jointure qui n'est généralement pas ce que vous voulez. Avoir l' la sélectivité pour réduire ce enlevé à un lointainWHERE
conditionnel signifie que vous êtes plus susceptible de faire des erreurs pendant la conception. - SQL-89
,
et SQL-92 expliciteJOIN
ont différents priorité.JOIN
a une priorité plus élevée. Pire encore, certaines bases de données comme MySQL se trompent depuis très longtemps. . Donc, mélanger les deux styles est une mauvaise idée, et le style beaucoup plus populaire aujourd'hui est le style SQL-92.