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 .