64

Does the SQL Server (2008 or 2012, specifically) CASE statement evaluate all the WHEN conditions or does it exit once it finds a WHEN clause that evaluates to true? If it does go through the entire set of conditions, does that mean that the last condition evaluating to true overwrites what the first condition that evaluated to true did? For example:

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

The results is "YES" even though the last when condition should make it evaluate to "NO". It seems that it exits once it finds the first TRUE condition. Can someone please confirm if this is the case.

1

4 Answers 4

61

•Returns the result_expression of the first input_expression = when_expression that evaluates to TRUE.

Reference https://learn.microsoft.com/sql/t-sql/language-elements/case-transact-sql


This is standard SQL behaviour:

  • A CASE expression evaluates to the first true condition.

  • If there is no true condition, it evaluates to the ELSE part.

  • If there is no true condition and no ELSE part, it evaluates to NULL.

1
  • 2
    I just wanted to make sure that if I have 3 case conditions that would all evaluate to true, I would only want the task of the first one that evaluates to true to be executed and not the other 2 (even though they also evaluated to true). From the example query in my questions this does seem to be the case. I just wanted to confirm. I was also hoping that SQL reads the CASE conditions from Top to Bottom. Thanks!
    – Juan Velez
    May 30, 2013 at 13:42
20

SQL Server usually does short-circuit evaluation for CASE statements (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;  

There are however several types of statements that as of SQL Server 2012 do not correctly short-circuit. See the link from ypercube in the comments.

Oracle always does short-circuit evaluation. See the 11.2 SQL Language Reference. Or compare the following (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;

This same test can't be done with MySQL because it returns NULL for division by zero. (SQL Fiddle)

5
  • How about this?: SQL-Fiddle May 30, 2013 at 13:24
  • 2
    The fiddle is about SQL-Server. It's Aaron's answer here: Does SQL Server read all of a COALESCE function even if the first argument is not NULL? May 30, 2013 at 13:39
  • @ypercube That is really interesting behavior. It is evaluating the code that would run in the else portion, but seems to ignore it depending on what other WHEN expressions exist and whether the divide by zero is inside a MIN or not. See sqlfiddle.com/#!6/d41d8/4468 May 30, 2013 at 13:52
  • @ypercube Now that I've read some of the link you posted, would you say that there are enough edge cases to say that the answer to whether SQL Server does short-circuit evaluation is - usually? May 30, 2013 at 13:58
  • 3
    Yes, I'd agree on "usually". As Aaron points on his answer, one test is enough to disprove the "CASE always short-circuits". But it usually does. May 30, 2013 at 14:19
8

It appears that MS SQL Server uses a short-circuit evaluation also.

In the following test I have 3 tests. The first one is always true, the second one fails without referencing the table, and the third fails only when the data is taken into account.
In this particular run both rows are returned successfully. If I comment out the first WHEN, or the first and second then I get failures.

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
0

if the case statement used in the WHERE condition and the first case when statement involve evaluating column values from the table, and the first row in the table does not satisfy this condition, the case statement will go to next case when statement.

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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.