Pernyataan ini sah (dengan kata lain, tidak FROM
diperlukan):
SELECT x = 1;
SELECT x = 1 WHERE 1 = 1; -- also try WHERE 1 = 0;
Kuncinya adalah ketika Anda memperkenalkan nama kolom yang jelas tidak bisa ada. Jadi ini gagal:
SELECT name WHERE 1 = 1;
SELECT x = 1 WHERE id > 0;
Msg 207, Level 16, Negara 1
Nama kolom 'nama' tidak valid.
Msg 207, Level 16, Negara 1
Nama kolom 'id' tidak valid.
Tetapi ketika kolom yang tidak valid diperkenalkan dalam sesuatu seperti subquery, apa yang SQL Server lakukan ketika tidak dapat menemukan kolom di lingkup dalam subquery, dilintasi ke lingkup luar, dan membuat subquery berkorelasi dengan lingkup luar itu. Ini akan mengembalikan semua baris, misalnya:
SELECT * FROM sys.columns WHERE name IN (SELECT name WHERE 1 = 1);
Karena pada dasarnya dikatakan:
SELECT * FROM sys.columns WHERE name IN (SELECT sys.columns.name WHERE 1 = 1); /*
^^^^^^^^^^^ -----------
| |
----------------------------------- */
Anda bahkan tidak perlu WHERE
klausa dalam subquery:
SELECT * FROM sys.columns WHERE name IN (SELECT name);
Anda dapat melihat bahwa itu benar-benar melihat ke luar pada meja yang dicakup, karena ini:
SELECT * FROM sys.columns WHERE name IN (SELECT name WHERE name > N'x');
Mengembalikan baris yang jauh lebih sedikit (11 di sistem saya).
Ini melibatkan kepatuhan terhadap standar tentang pelingkupan. Anda dapat melihat hal-hal serupa ketika Anda memiliki dua tabel #temp:
CREATE TABLE #foo(foo int);
CREATE TABLE #bar(bar int);
SELECT foo FROM #foo WHERE foo IN (SELECT foo FROM #bar);
Jelas, ini kesalahan, kan, karena tidak ada foo
di #bar
? Nggak. Apa yang terjadi adalah bahwa SQL Server berkata, "oh, saya tidak menemukan di foo
sini, Anda pasti maksud yang lain."
Juga, secara umum, saya akan menghindari NOT IN
. NOT EXISTS
memiliki potensi untuk menjadi lebih efisien dalam beberapa skenario, tetapi yang lebih penting, perilakunya tidak berubah ketika mungkin bahwa kolom target bisa NULL
. Lihat posting ini untuk info lebih lanjut .
Saya mereproduksi ini pada tahun 2016 dengan contoh sederhana:
Tampaknya c2 dan c3 dievaluasi untuk setiap baris.
sumber
Dalam SQL Server SELECT sintaks tidak memerlukan bagian DARI. Jika Anda menghilangkan FROM, pernyataan pilih akan menggunakan tabel "dummy" yang memiliki satu baris dan tidak ada kolom. Begitu
akan mengembalikan satu baris jika ekspresi itu benar dan tidak ada baris ketika itu salah.
sumber
select c
danc
tidak ada di beberapa objek luar. Saya setuju bahwaFROM
tidak diperlukan, tetapi mekanisme yang dimainkan di sini ketika Anda secara eksplisit menyebutkan kolom yang memang ada di lingkup luar pasti berbeda dari tabel dummy, dan jika Anda tidak memberikan konstanta untuk kolom yang tidak ada, Anda mendapatkan kesalahan runtime, jadi tidak ada tabel dummy di sana. Tabel Dummy dapat ikut bermain dalam skenario lain, tetapi tidak ketika referensi berada dalam tabel subquery / turunan.SELECT 'x' AS c
adalah skenario yang sama sekali berbeda dari skenario OP, yang baru saja mengatakanSELECT c
. Dalam tabel subquery / turunan.