Sommaire
Il n'y a aucune raison logique que cela ne puisse pas être fait, mais l'avantage est faible et il y a des pièges qui ne sont pas immédiatement apparents.
Résultats de recherche
J'ai fait quelques recherches et trouvé de bonnes informations. Ce qui suit est une citation directe d'une source principale fiable (qui souhaite rester anonyme) au 2012-08-09 17:49 GMT:
Lorsque SQL a été inventé pour la première fois, il n'avait aucun alias dans la clause SELECT. Il s'agissait d'une grave lacune qui a été corrigée lorsque le langage a été normalisé par l'ANSI vers 1986.
Le langage était censé être "non procédural" - en d'autres termes, pour décrire les données que vous souhaitez sans préciser comment les trouver. Donc, pour autant que je sache, il n'y a aucune raison pour qu'une implémentation SQL ne puisse pas analyser la requête entière avant de la traiter et permettre aux alias d'être définis n'importe où et utilisés partout. Par exemple, je ne vois aucune raison pour laquelle la requête suivante ne devrait pas être valide:
select name, salary + bonus as pay
from employee
where pay > 100000
Bien que je pense qu'il s'agit d'une requête raisonnable, certains systèmes basés sur SQL peuvent introduire des restrictions sur l'utilisation des alias pour une raison liée à l'implémentation. Je ne suis pas surpris d'apprendre que SQL Server fait cela.
Je suis intéressé par d'autres recherches sur la norme SQL-86 et pourquoi les SGBD modernes ne prennent pas en charge la réutilisation des alias, mais je n'ai pas encore eu le temps d'aller très loin avec. Pour commencer, je ne sais pas où obtenir la documentation ni comment savoir exactement qui a constitué le comité. Quelqu'un peut-il m'aider? J'aimerais également en savoir plus sur le produit Sybase d'origine dont SQL Server est issu.
À partir de ces recherches et de certaines réflexions, j'ai fini par soupçonner que l'utilisation d'alias dans d'autres clauses, bien que tout à fait possible, n'a tout simplement jamais été une priorité aussi élevée pour les fabricants de SGBD par rapport aux autres fonctionnalités de langage. Comme ce n'est pas vraiment un obstacle, être facilement contourné par le rédacteur de requêtes, y consacrer des efforts par rapport aux autres avancées n'est pas optimal. De plus, il serait propriétaire car il ne fait évidemment pas partie du standard SQL (bien que j'attende pour en savoir plus à ce sujet) et serait donc une amélioration mineure, brisant la compatibilité SQL entre les SGBD. En comparaison, CROSS APPLY
(qui n'est vraiment rien de plus qu'un tableau dérivé permettant des références externes) est un énorme changement, qui, bien que propriétaire, offre une puissance expressive incroyable qui n'est pas facilement exécutée d'autres manières.
Problèmes avec l'utilisation d'alias partout
Si vous autorisez la mise d'éléments SELECT dans la clause WHERE, vous pouvez non seulement exploser la complexité de la requête (et donc la complexité de trouver un bon plan d'exécution), mais il est possible de trouver des choses complètement illogiques. Essayer:
SELECT X + 5 Y FROM MyTable WHERE Y = X
Que faire si MyTable a déjà une colonne Y, à laquelle la clause WHERE fait-elle référence? La solution consiste à utiliser un CTE ou une table dérivée, qui dans la plupart des cas ne devrait pas coûter plus cher mais atteint le même résultat final. Les CTE et les tables dérivées appliquent au moins la résolution de l'ambiguïté en permettant à un alias d'être utilisé une seule fois.
En outre, ne pas utiliser d'alias dans la clause FROM est parfaitement logique. Vous ne pouvez pas faire ça:
SELECT
T3.ID + (SELECT Min(Interval) FROM Intervals WHERE IntName = 'T') CalcID
FROM
Table1 T
INNER JOIN Table2 T2
ON T2.ID = CalcID
INNER JOIN Table3 T3
ON T2.ID = T3.ID
C'est une référence circulaire (dans le sens où T2 fait secrètement référence à une valeur de T3, avant que ce tableau ait été présenté dans la liste JOIN), et sacrément difficile à voir. Celui-ci, ça va:
INSERT dbo.FinalTransaction
SELECT
newid() FinalTransactionGUID,
'GUID is: ' + Convert(varchar(50), FinalTransactionGUID) TextGUID,
T.*
FROM
dbo.MyTable T
À quel point voulez-vous parier que la fonction newid () va être placée deux fois dans le plan d'exécution, de manière complètement inattendue, faisant que les deux colonnes affichent des valeurs différentes? Qu'en est-il lorsque la requête ci-dessus est utilisée N niveaux en profondeur dans les CTE ou les tables dérivées Je vous garantis que le problème est pire que vous ne pouvez l'imaginer. Il existe déjà de graves problèmes d'incohérence concernant le moment où les choses sont évaluées une seule fois ou à quel moment dans un plan de requête, et Microsoft a déclaré qu'il ne résoudrait pascertains d'entre eux parce qu'ils expriment correctement l'algèbre de requête - si l'on obtient des résultats inattendus, divisez la requête en plusieurs parties. Autoriser les références chaînées, détecter les références circulaires à travers de très longues chaînes de ce type - ce sont des problèmes assez délicats. Introduisez le parallélisme et vous avez un cauchemar en devenir.
Remarque: L'utilisation de l'alias dans WHERE ou GROUP BY ne va pas faire de différence avec les fonctions telles que newid () ou rand ().
Une façon SQL Server de créer des expressions réutilisables
CROSS APPLY / OUTER APPLY est une façon dans SQL Server de créer des expressions qui peuvent être utilisées n'importe où ailleurs dans la requête (mais pas plus tôt dans la clause FROM):
SELECT
X.CalcID
FROM
Table1 T
INNER JOIN Table3 T3
ON T.ID = T3.ID
CROSS APPLY (
SELECT
T3.ID + (SELECT Min(Interval) FROM Intervals WHERE IntName = 'T') CalcID
) X
INNER JOIN Table2 T2
ON T2.ID = X.CalcID
Cela fait deux choses:
- Fait en sorte que toutes les expressions dans CROSS APPLY obtiennent un "espace de noms" (un alias de table, ici, X) et soient uniques dans cet espace de noms.
- Il est évident partout non seulement que CalcID provient de X, mais rend également évident pourquoi vous ne pouvez pas utiliser quoi que ce soit de X lorsque vous rejoignez les tables T1 et T3, car X n'a pas encore été introduit.
En fait, j'aime beaucoup CROSS APPLY. Il est devenu mon fidèle ami et je l'utilise tout le temps. Besoin d'un UNPIVOT partiel (qui nécessiterait un PIVOT / UNPIVOT ou UNPIVOT / PIVOT utilisant la syntaxe native)? Fait avec CROSS APPLY. Besoin d'une valeur calculée qui sera réutilisée plusieurs fois? Terminé. Besoin d'appliquer rigoureusement l'ordre d'exécution des appels sur un serveur lié? Fait avec une amélioration criante de la vitesse. Besoin d'un seul type de ligne divisée en 2 lignes ou avec des conditions supplémentaires? Terminé.
Donc, à tout le moins, dans DBMS SQL Server 2005 et versions ultérieures, vous n'avez plus de motif de plainte: CROSS APPLY est la façon dont vous SÉCHEZ comme vous le souhaitez.