web-dev-qa-db-ja.com

SQL Server CASEステートメントはすべての条件を評価しますか、それとも最初のTRUE条件で終了しますか?

SQL Server(具体的には2008または2012)CASEステートメントは、すべてのWHEN条件を評価しますか、それとも、trueと評価されるWHEN句を見つけたら終了しますか?条件のセット全体を通過する場合、それは、trueと評価された最後の条件が、trueと評価された最初の条件が行ったことを上書きすることを意味しますか?例えば:

SELECT
    CASE
        WHEN 1+1 = 2 THEN'YES'
        WHEN 1+1 = 3 THEN 'NO'
        WHEN 1+1 = 2 THEN 'NO' 
    END

最後のwhen条件で「NO」と評価されても、結果は「YES」になります。最初のTRUE条件が見つかると終了するようです。誰かがこれがcaseであるかどうかを確認してください。

45
Juan Velez

firstinput_expression = when_expressionのresult_expressionを返し、TRUEと評価。

リファレンス http://msdn.Microsoft.com/en-us/library/ms181765.aspx


これは標準SQLの動作です。

  • CASE式は最初の真の条件に評価されます。

  • 真の条件がない場合は、ELSE部分として評価されます。

  • 真の条件がなく、ELSE部分もない場合、NULLと評価されます。

47
James Jenkins

SQL Serverは通常、CASEステートメントの短絡評価SQLFiddle )を実行します。

--Does not fail on the divide by zero.
SELECT 
   CASE 
      WHEN 1/1 = 1 THEN 'Case 1'
      WHEN 2/0 = 1 THEN 'Case 2'
   END;

--Fails on the divide by zero.
SELECT 
   CASE 
      WHEN 1/1 = 99 THEN 'Case 1'
      WHEN 2/0 = 99 THEN 'Case 2'
   END;  

ただし、SQL Server 2012の時点で正しく短絡しないいくつかの種類のステートメントがあります。コメントでypercubeからのリンクを参照してください。

Oracleは常に短絡評価を行います。 11.2 SQL言語リファレンス を参照してください。または、次の比較( SQLFiddle ):

--Does not fail on the divide by zero.
SELECT
  CASE 
    WHEN 1/1 = 1 THEN 'Case 1'
    WHEN 2/0 = 1 THEN 'Case 2'
  END
FROM dual;


--Fails on the divide by zero.
SELECT
  CASE 
    WHEN 1/1 = 99 THEN 'Case 1'
    WHEN 2/0 = 99 THEN 'Case 2'
  END
FROM dual;

これと同じテストは、ゼロ除算に対してNULLを返すため、MySQLでは実行できません。 ( SQLフィドル

15
Leigh Riffel

MS SQL Serverも短絡評価を使用しているようです。

次のテストでは、3つのテストがあります。 1つ目は常にtrue、2つ目はテーブルを参照せずに失敗し、3つ目はデータが考慮された場合にのみ失敗します。
この特定の実行では、両方の行が正常に返されます。最初のWHEN、または最初と2番目のコメントをコメントアウトすると、失敗します。

CREATE TABLE casetest (test varchar(10))
GO
INSERT INTO casetest VALUES ('12345'),('abcdef')
GO

SELECT CASE WHEN LEN(test)>1 THEN test
        WHEN 1/0 = 1 THEN 'abc'
        WHEN CAST(test AS int) = 1 THEN 'def'
        END
FROM casetest
GO
7
Kenneth Fisher

MySQLでは、最初のtrueオプションでcaseステートメントを終了します。複数の真の値の可能性がある場合は、優先する回答をシーケンスの前に配置する必要があります。

1
Rob

WHERE条件で使用されるcaseステートメントと最初のcaseステートメントがテーブルの列値の評価に関係し、テーブルの最初の行がこの条件を満たさない場合、caseステートメントは次のケースに進みますステートメント。

declare @tbl table(id int)
insert into @tbl values(1)
insert into @tbl values(2)
insert into @tbl values(3)

--Fails on the divide by zero.
SELECT * FROM @tbl
where  CASE 
        WHEN id = 2 THEN 1 -- first row in table will not satisfy the condition
        WHEN 2/0 = 1 THEN 1
        ELSE 0
      END =1

-- when filter the records to only who will staisfy the first case when condition, it 
will not fail on the divide by zero
SELECT * FROM @tbl
where ID=2 and -- first row in table will  satisfy the condition
  CASE 
    WHEN id = 2 THEN 1
    WHEN 2/0 = 1 THEN 1
    ELSE 0
  END =1
1