Zusammenfassung
Es gibt keinen logischen Grund, warum dies nicht möglich ist, aber der Nutzen ist gering und es gibt einige Fallstricke, die möglicherweise nicht sofort erkennbar sind.
Forschungsergebnisse
Ich habe ein paar Nachforschungen angestellt und gute Informationen gefunden. Das Folgende ist ein direktes Zitat aus einer zuverlässigen Primärquelle (die anonym bleiben möchte) am 2012-08-09 17:49 GMT:
Als SQL zum ersten Mal erfunden wurde, hatte es keine Aliase in der SELECT-Klausel. Dies war ein schwerwiegender Mangel, der behoben wurde, als die Sprache 1986 von ANSI standardisiert wurde.
Die Sprache sollte "nicht prozedural" sein, dh die gewünschten Daten beschreiben, ohne anzugeben, wie sie gefunden werden sollen. Soweit ich weiß, gibt es keinen Grund, warum eine SQL-Implementierung nicht die gesamte Abfrage analysieren kann, bevor sie verarbeitet wird. Außerdem können Aliase überall definiert und verwendet werden. Zum Beispiel sehe ich keinen Grund, warum die folgende Abfrage nicht gültig sein sollte:
select name, salary + bonus as pay
from employee
where pay > 100000
Obwohl ich dies für eine vernünftige Abfrage halte, können einige SQL-basierte Systeme aus Gründen der Implementierung Einschränkungen für die Verwendung von Aliasnamen einführen. Ich bin nicht überrascht zu hören, dass SQL Server dies tut.
Ich bin an weiteren Forschungen zum SQL-86-Standard interessiert und daran, warum moderne DBMS die Wiederverwendung von Aliasen nicht unterstützen, aber noch nicht die Zeit hatten, damit sehr weit zu kommen. Für den Anfang weiß ich nicht, wo ich die Dokumentation bekommen soll oder wie ich herausfinden kann, wer genau das Komitee gebildet hat. Kann mir jemand helfen? Ich möchte auch mehr über das ursprüngliche Sybase-Produkt erfahren, von dem SQL Server stammt.
Aufgrund dieser Nachforschungen und einiger weiterer Überlegungen habe ich den Verdacht, dass die Verwendung von Aliasnamen in anderen Klauseln, obwohl dies durchaus möglich ist, für DBMS-Hersteller im Vergleich zu anderen Sprachfunktionen noch nie so hohe Priorität hatte. Da dies kein allzu großes Hindernis darstellt, ist es nicht optimal, wenn der Query-Writer dies leicht umgeht und sich mehr Mühe gibt, als andere Verbesserungen. Darüber hinaus wäre es proprietär, da es offensichtlich nicht Teil des SQL-Standards ist (obwohl ich sicher darauf warte, mehr darüber herauszufinden) und daher eine geringfügige Verbesserung wäre, die die SQL-Kompatibilität zwischen DBMS-Systemen unterbricht. Im Vergleich dazu CROSS APPLY
(was eigentlich nichts anderes als eine abgeleitete Tabelle ist, die äußere Verweise zulässt) handelt es sich um eine enorme Veränderung, die, obwohl proprietär, eine unglaubliche Ausdruckskraft bietet, die auf andere Weise nicht einfach zu realisieren ist.
Probleme mit der Verwendung von Aliasen überall
Wenn Sie zulassen, dass SELECT-Elemente in die WHERE-Klausel aufgenommen werden, können Sie nicht nur die Komplexität der Abfrage (und damit die Komplexität, einen guten Ausführungsplan zu finden) aufklären, sondern auch völlig unlogische Dinge. Versuchen:
SELECT X + 5 Y FROM MyTable WHERE Y = X
Was passiert, wenn MyTable bereits eine Spalte Y enthält, auf die sich die WHERE-Klausel bezieht? Die Lösung besteht darin, einen CTE oder eine abgeleitete Tabelle zu verwenden, was in den meisten Fällen keine zusätzlichen Kosten verursacht, aber dasselbe Endergebnis erzielt. CTEs und abgeleitete Tabellen erzwingen zumindest die Auflösung von Mehrdeutigkeiten, indem ein Alias nur einmal verwendet werden darf.
Es ist auch sehr sinnvoll, in der FROM-Klausel keine Aliase zu verwenden. Das kannst du nicht machen:
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
Das ist ein Zirkelverweis (in dem Sinne, dass T2 sich heimlich auf einen Wert aus T3 bezieht, bevor diese Tabelle in der JOIN-Liste aufgeführt wurde) und verdammt schwer zu sehen. Wie wäre es mit diesem:
INSERT dbo.FinalTransaction
SELECT
newid() FinalTransactionGUID,
'GUID is: ' + Convert(varchar(50), FinalTransactionGUID) TextGUID,
T.*
FROM
dbo.MyTable T
Wie viel möchten Sie wetten, dass die newid () - Funktion zweimal in den Ausführungsplan aufgenommen wird, sodass die beiden Spalten völlig unerwartet unterschiedliche Werte anzeigen? Was ist, wenn die obige Abfrage N Ebenen tief in CTEs oder abgeleiteten Tabellen verwendet wird. Ich garantiere, dass das Problem schlimmer ist, als Sie sich vorstellen können. Es gibt bereits schwerwiegende Inkonsistenzprobleme, wenn Dinge nur einmal ausgewertet werden oder zu welchem Zeitpunkt in einem Abfrageplan, und Microsoft hat angegeben, dass dies nicht behoben werden kannEinige davon, weil sie die Abfrage-Algebra korrekt ausdrücken. Wenn Sie unerwartete Ergebnisse erhalten, teilen Sie die Abfrage in Teile auf. Zulassen von verketteten Referenzen, Erkennen von Zirkelreferenzen durch möglicherweise sehr lange solche Ketten - dies sind recht knifflige Probleme. Führen Sie Parallelität ein und Sie haben einen Albtraum im Entstehen.
Hinweis: Die Verwendung des Alias in WHERE oder GROUP BY hat keinen Einfluss auf die Probleme mit Funktionen wie newid () oder rand ().
Eine SQL Server-Methode zum Erstellen wiederverwendbarer Ausdrücke
CROSS APPLY / OUTER APPLY ist eine Möglichkeit in SQL Server, Ausdrücke zu erstellen, die an einer anderen Stelle in der Abfrage verwendet werden können (nur nicht früher in der FROM-Klausel):
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
Das macht zwei Dinge:
- Lässt alle Ausdrücke in CROSS APPLY einen "Namespace" (ein Tabellenalias, hier X) erhalten und in diesem Namespace eindeutig sein.
- Verdeutlicht überall, dass CalcID nicht nur von X stammt, sondern auch, warum Sie beim Verknüpfen der Tabellen T1 und T3 nichts von X verwenden können, da X noch nicht eingeführt wurde.
Eigentlich mag ich CROSS APPLY. Es ist mein treuer Freund geworden und ich benutze es die ganze Zeit. Benötigen Sie einen unvollständigen UNPIVOT (für den PIVOT / UNPIVOT oder UNPIVOT / PIVOT mit nativer Syntax erforderlich wäre)? Fertig mit CROSS APPLY. Benötigen Sie einen berechneten Wert, der viele Male wiederverwendet wird? Erledigt. Müssen Sie die Ausführungsreihenfolge für Anrufe über einen Verbindungsserver streng erzwingen? Fertig mit einer schreienden Geschwindigkeitsverbesserung. Benötigen Sie nur einen Zeilentyp, der in zwei Zeilen aufgeteilt ist, oder zusätzliche Bedingungen? Erledigt.
Zumindest in DBMS SQL Server 2005 und höher gibt es also keinen Grund mehr, sich zu beschweren: Mit CROSS APPLY trocknen Sie so, wie Sie es möchten.