このステートメントは合法です(つまり、FROM
必要ありません)。
SELECT x = 1;
SELECT x = 1 WHERE 1 = 1; -- also try WHERE 1 = 0;
トリックは、明らかに存在できない列名を導入するときです。したがって、これらは失敗します:
SELECT name WHERE 1 = 1;
SELECT x = 1 WHERE id > 0;
メッセージ207、レベル16、状態1
無効な列名 'name'。
メッセージ207、レベル16、状態1
無効な列名 'id'。
ただし、無効な列がサブクエリのようなものに導入された場合、SQL Serverがサブクエリの内部スコープでその列を見つけられなかった場合のSQL Serverの動作は、外部スコープに移動し、サブクエリをその外部スコープに関連付けます。これにより、すべての行が返されます。次に例を示します。
SELECT * FROM sys.columns WHERE name IN (SELECT name WHERE 1 = 1);
それは本質的に言っているので:
SELECT * FROM sys.columns WHERE name IN (SELECT sys.columns.name WHERE 1 = 1); /*
^^^^^^^^^^^ -----------
| |
----------------------------------- */
WHERE
サブクエリに句も必要ありません。
SELECT * FROM sys.columns WHERE name IN (SELECT name);
次の理由により、実際は外側のスコープテーブルを参照していることがわかります。
SELECT * FROM sys.columns WHERE name IN (SELECT name WHERE name > N'x');
はるかに少ない行を返します(私のシステムでは11)。
これには、スコーピングに関する標準への準拠が含まれます。#tempテーブルが2つある場合、同様のことがわかります。
CREATE TABLE #foo(foo int);
CREATE TABLE #bar(bar int);
SELECT foo FROM #foo WHERE foo IN (SELECT foo FROM #bar);
何もありませんので、明らかに、これは、右、エラーすべきfoo
では#bar
?いいえ。何が起こるのかというと、SQL Serverは、「ああ、私はfoo
ここを見つけられませんでした。もう一方を意味しているに違いありません」と言っています。
また、一般的には避けNOT IN
ます。NOT EXISTS
一部のシナリオではより効率的になる可能性がありますが、さらに重要なことに、ターゲット列が可能である可能性がある場合、その動作は変更されませんNULL
。詳細については、この投稿を参照してください。