変数に値を指定するシナリオに取り組んでいます。 Null値を渡すと、クエリエンジンは結合テーブルをスキャンしませんでした。論理クエリ処理に従って、最初に[〜#〜] from [〜#〜]句が実行され、次に[ 〜#〜] on [〜#〜]および[〜#〜] join [〜#〜]が実行されます。ただし、この場合、クエリエンジンはWhere句に直接移動します。変数にNULL値がある場合の動作クエリエンジンについて説明してください。 SQL Server 2016を使用しています。
値が変更されると
矛盾検出 の例が表示されています。 SQL Serverのクエリオプティマイザーは、クエリ処理の最初にいくつかのクイックチェックを実行して、多くの(何でもない!)作業を行わずに結果を返すためのショートカットを取ることができるかどうかを判断するのに十分スマートです。このような短絡の1つは、where句に次のような「不可能な」制限が含まれているかどうかを確認することです。
WHERE 1=0
または
WHERE NULL = NULL
SQL Serverは、何かをNULL
と比較していることを確認します。alwaysはfalseを返し、単に空の結果セットを返します。 WHERE
句の項目がOR
ではなくAND
で区切られている場合、さらにチェックが実行され、定数スキャン計画が表示されない可能性があります。
=
alwaysを使用して任意の値をNULL
と比較すると、falseが返されます。代わりにWHERE @c IS NULL
を使用できます。その構文を使用してクエリを書き換えると、SQL Serverが実際にクエリを「実行」することがわかります。このことを考慮:
IF OBJECT_ID(N'tempdb..#t', N'U') IS NOT NULL DROP TABLE #t;
CREATE TABLE #t
(
i int NOT NULL
);
DECLARE @c int = 1;
このクエリのクエリプラン:
SELECT *
FROM #t t
WHERE t.i = 1
AND @c = NULL;
このクエリのクエリプランとの比較:
SELECT *
FROM #t t
WHERE t.i = 1
AND @c IS NULL;
NULL
値の比較に関する問題は、JOIN
条件にも当てはまります。このことを考慮:
IF OBJECT_ID(N'tempdb..#t', N'U') IS NOT NULL DROP TABLE #t;
CREATE TABLE #t
(
i int NULL
);
IF OBJECT_ID(N'tempdb..#s', N'U') IS NOT NULL DROP TABLE #s;
CREATE TABLE #s
(
i int NULL
);
i
の値をNULL
に設定して、各テーブルに行を挿入します。
INSERT INTO #t (i) VALUES (NULL);
INSERT INTO #s (i) VALUES (NULL);
ここで、「単純な」クエリで2つのテーブルをJOIN
しようとすると、NULL
は他のNULL
とさえ比較できないため、結果は返されません。値!
SELECT *
FROM #t t
INNER JOIN #s s ON t.i = s.i;
クエリプランに示されているように、両方のテーブルがクエリプロセッサによってスキャンされます。
つまり、NULL
値の使用には注意が必要です。
今後は、コードの画像を投稿しないでください。代わりに、他の人が回答に使用できる 最小限、完全、検証可能な例 を作成してください。