To oświadczenie jest legalne (innymi słowy, nie FROM
jest wymagane):
SELECT x = 1;
SELECT x = 1 WHERE 1 = 1; -- also try WHERE 1 = 0;
Sztuką jest wprowadzenie nazwy kolumny, która najwyraźniej nie może istnieć. Te zawodzą:
SELECT name WHERE 1 = 1;
SELECT x = 1 WHERE id > 0;
Msg 207, poziom 16, stan 1
Niepoprawna nazwa kolumny „nazwa”.
Msg 207, poziom 16, stan 1
Niepoprawna nazwa kolumny „id”.
Ale gdy niepoprawna kolumna zostanie wprowadzona do czegoś w rodzaju podkwerendy, to co SQL Server robi, gdy nie może znaleźć tej kolumny w wewnętrznym zakresie podkwerendy, przechodzi do zakresu zewnętrznego i powoduje, że podkwerenda jest skorelowana z tym zakresem zewnętrznym. Zwróci to wszystkie wiersze, na przykład:
SELECT * FROM sys.columns WHERE name IN (SELECT name WHERE 1 = 1);
Ponieważ zasadniczo mówi:
SELECT * FROM sys.columns WHERE name IN (SELECT sys.columns.name WHERE 1 = 1); /*
^^^^^^^^^^^ -----------
| |
----------------------------------- */
Nie potrzebujesz nawet WHERE
klauzuli w podzapytaniu:
SELECT * FROM sys.columns WHERE name IN (SELECT name);
Widać, że naprawdę patrzy na zewnętrzny stół z lunetą, ponieważ to:
SELECT * FROM sys.columns WHERE name IN (SELECT name WHERE name > N'x');
Zwraca znacznie mniej wierszy (11 w moim systemie).
Wymaga to przestrzegania standardu określania zakresu. Możesz zobaczyć podobne rzeczy, gdy masz dwie tabele #temp:
CREATE TABLE #foo(foo int);
CREATE TABLE #bar(bar int);
SELECT foo FROM #foo WHERE foo IN (SELECT foo FROM #bar);
Oczywiście, należy ten błąd, w prawo, ponieważ nie jest foo
w #bar
? Nie. To, co się dzieje, to to, że SQL Server mówi: „och, nie znalazłem foo
tutaj, musiałeś mieć na myśli ten drugi”.
Poza tym ogólnie bym unikał NOT IN
. NOT EXISTS
ma potencjał, aby być bardziej wydajnym w niektórych scenariuszach, ale co ważniejsze, jego zachowanie nie zmienia się, gdy możliwe jest, że kolumna docelowa mogłaby być NULL
. Zobacz ten post, aby uzyskać więcej informacji .
Powtórzyłem to w 2016 roku na uproszczonym przykładzie:
Wygląda na to, że c2 i c3 są oceniane dla każdego wiersza.
źródło
W SQL Server składnia SELECT nie wymaga sekcji OD. Jeśli pominiesz FROM, instrukcja select użyje „sztucznej” tabeli, która ma jeden wiersz i nie zawiera kolumn. Więc
zwróci jeden wiersz, jeśli wyrażenie jest prawdziwe, a żadnych wierszy, gdy jest fałszem.
źródło
select c
ic
nie istnieje w jakimś zewnętrznym obiekcie. Zgadzam się, żeFROM
nie jest to wymagane, ale mechanika w grze tutaj, gdy jawnie nazwiesz kolumnę, która istnieje w zasięgu zewnętrznym, zdecydowanie różni się od tabeli zastępczej i jeśli nie podasz stałej dla kolumny, która nie istnieje, pojawia się błąd czasu wykonania, więc nie ma tam również tabeli zastępczej. Tabela manekina może wejść w grę w innych scenariuszach, ale nie wtedy, gdy odwołanie znajduje się w tabeli podzapytania / pochodnej.SELECT 'x' AS c
to zupełnie inny scenariusz niż PO, który właśnie powiedziałSELECT c
. W tabeli podzapytań / pochodnych.