Diese Aussage ist legal (mit anderen Worten, nein FROM
ist erforderlich):
SELECT x = 1;
SELECT x = 1 WHERE 1 = 1; -- also try WHERE 1 = 0;
Der Trick ist, wenn Sie einen Spaltennamen einführen, der eindeutig nicht existieren kann. Also scheitern diese:
SELECT name WHERE 1 = 1;
SELECT x = 1 WHERE id > 0;
Meldung 207, Ebene 16, Status 1
Ungültiger Spaltenname 'Name'.
Meldung 207, Ebene 16, Status 1
Ungültiger Spaltenname 'id'.
Wenn die ungültige Spalte jedoch in eine Unterabfrage eingefügt wird, wird SQL Server, wenn es diese Spalte im inneren Bereich der Unterabfrage nicht findet, zu einem äußeren Bereich durchlaufen und die Unterabfrage mit diesem äußeren Bereich korrelieren lassen. Dies gibt alle Zeilen zurück, zum Beispiel:
SELECT * FROM sys.columns WHERE name IN (SELECT name WHERE 1 = 1);
Weil es im Wesentlichen heißt:
SELECT * FROM sys.columns WHERE name IN (SELECT sys.columns.name WHERE 1 = 1); /*
^^^^^^^^^^^ -----------
| |
----------------------------------- */
Sie brauchen nicht einmal eine WHERE
Klausel in der Unterabfrage:
SELECT * FROM sys.columns WHERE name IN (SELECT name);
Sie können sehen, dass es wirklich auf den äußeren Bereichstisch schaut, weil dies:
SELECT * FROM sys.columns WHERE name IN (SELECT name WHERE name > N'x');
Gibt weit weniger Zeilen zurück (11 auf meinem System).
Dies beinhaltet die Einhaltung des Standards für das Scoping. Sie können ähnliche Dinge sehen, wenn Sie zwei # temp-Tabellen haben:
CREATE TABLE #foo(foo int);
CREATE TABLE #bar(bar int);
SELECT foo FROM #foo WHERE foo IN (SELECT foo FROM #bar);
Offensichtlich sollte dies ein Fehler sein, oder, da es kein foo
In gibt #bar
? Nee. Was passiert ist, dass SQL Server sagt: "Oh, ich habe hier keine foo
gefunden, Sie müssen die andere gemeint haben."
Auch im Allgemeinen würde ich vermeiden NOT IN
. NOT EXISTS
hat das Potenzial, in einigen Szenarien effizienter zu sein, aber was noch wichtiger ist, sein Verhalten ändert sich nicht, wenn es möglich ist, dass die Zielspalte sein könnte NULL
. Weitere Informationen finden Sie in diesem Beitrag .
Ich habe dies 2016 mit einem vereinfachten Beispiel reproduziert:
Es scheint, dass c2 und c3 für jede Zeile ausgewertet werden.
quelle
In SQL Server erfordert die SELECT-Syntax keinen FROM-Abschnitt. Wenn Sie FROM weglassen, verwendet die select-Anweisung eine "Dummy" -Tabelle mit einer Zeile und keinen Spalten. So
gibt eine Zeile zurück, wenn der Ausdruck wahr ist, und keine Zeilen, wenn er falsch ist.
quelle
select c
undc
existiert nicht in einem äußeren Objekt. Ich bin damit einverstanden, dass diesFROM
nicht erforderlich ist, aber die hier verwendeten Mechanismen, wenn Sie eine Spalte, die in einem äußeren Bereich vorhanden ist, explizit benennen, unterscheiden sich definitiv von einer Dummy-Tabelle, und wenn Sie keine Konstante für eine Spalte angeben, die dies nicht tut vorhanden, erhalten Sie einen Laufzeitfehler, also auch keine Dummy-Tabelle. Dummy-Tabellen können in anderen Szenarien ins Spiel kommen, jedoch nicht, wenn sich die Referenz in einer Unterabfrage / abgeleiteten Tabelle befindet.SELECT 'x' AS c
ist ein völlig anderes Szenario als die OPs, die es gerade gesagt habenSELECT c
. In einer Unterabfrage / abgeleiteten Tabelle.