このSQL文がどのように動作します:あなたはこのように見てWHERE
句を変更する必要がありますか?
論理的に質問していますか?
SQLは3つの論理を使用します。個々の述語は、真、偽、または未知のいずれかと評価できます。
例では、真理値表をOR
と考えて、述部を結合して全体的な結果を得る方法を調べる必要があります。行が結果に返されるため、全体的な述語がtrue
に評価しなければならないWHERE
句の文脈において
。
上記の真理値表は、いずれかの述語が真であることを知ることで十分であることを示しています。したがって、最初のものが真であると評価された場合、2番目のものを評価する必要はありません。これは、短絡回路評価として知られています。
SQL Serverでは、評価の順序または短絡評価のどちらも保証されません。
例
DECLARE @Table TABLE (
column1 VARCHAR(50) PRIMARY KEY);
INSERT INTO @Table
VALUES ('brand1'),
('brand2'),
('brand3')
DECLARE @brand VARCHAR(50) = 'brand1'
SELECT *
FROM @Table
WHERE (column1 = @brand
OR @brand = '*');
実行プランは、テーブル全体がスキャンされ、次の
と述語が各行で評価を示しています。 SQL Serverは、表示された順序で条件を評価する場合と評価しない場合があり、短絡評価を使用する場合と使用しない場合があります。この情報は私たちには公開されていません。
最初の行が返されます。
効率
上記のクエリのセマンティックは、これが主キーをサポートしている索引に対する簡単な検索で評価することが可能であるべきちょうど
SELECT *
FROM @Table
WHERE column1= 'brand1'
です - テーブル全体をスキャンしません。 SQL Server 2008のから
以降、あなたはそれを実行する前に、この文を再コンパイルし、次の
DECLARE @brand VARCHAR(50) = 'brand1'
SELECT *
FROM @Table
WHERE (column1 = @brand OR @brand = '*')
OPTION (RECOMPILE)
を使用することができますし、実行計画をキャッシュしません。つまり、この計画では、具体的な値@brand
を考慮に入れることができます。
今@brand = '*'
の比較は、コンパイル時に行われ、偽であると判断し、述語はcolumn1 = 'brand1'
に簡略化される - インデックスは、その特定の値を求めることが可能となります。
だから、最初にどのようにそれは 'column1'にそれを適用するために知っている、は' true'として '@brand = '*''評価された場合? (それ以上の比較は行われないので)。私はそれが '@brand = '*''を見て、 'column1 = @ brand'ではないと思っています。 – sojim2
@ sojim2それはポイントです - それは' column1'には適用されません。 'OR'節では、一方の側だけが' TRUE'である必要があります - したがって、両方の節が実行される唯一の方法は、一方または両方の文が 'FALSE'である場合です。 – Ruslan
例として、この(非SQL)コードをチェックアウトしてください:http://ideone.com/GmzhHU(SQLは式の中に副作用を許さないので、私はあなたにそのような例を与えることはできません)。 'OR'に基づく' if'文( '||')がどのように存在し、最初の関数だけがどのように実行されるかに注意してください。それは「真」をもたらすので、第2のものは動かす必要はない。プログラムは、最初のものが真であれば、文全体が真(1または0 = 1)であることをすでに知っています。これは短絡*と呼ばれます(ただし、SQL Serverでは同じ方法で短絡が行われることはありませんが、この質問の範囲を超えています)。 – Ruslan