Answers:
•返回评估为TRUE的第一个 input_expression = when_expression 的result_expression 。
参考 http://msdn.microsoft.com/en-us/library/ms181765.aspx
这是标准的SQL行为:
甲CASE
表达式计算为第一真条件。
如果没有真实条件,它将评估ELSE
零件。
如果没有真实条件,也没有ELSE
分量,则结果为NULL
。
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;
MySQL无法进行相同的测试,因为它会返回NULL以除以零。(SQL小提琴)
看来MS SQL Server也使用短路评估。
在以下测试中,我有3个测试。第一个始终为真,第二个始终不引用表而失败,而第三个仅在考虑了数据后才会失败。
在此特定运行中,成功返回了两行。如果我注释掉第一个WHEN或第一个和第二个,那么我会失败。
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
如果WHERE
条件中使用的case语句和when语句中的第一个case语句涉及评估表中的列值,并且表中的第一行不满足此条件,则case语句将转到下一个case when语句。
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
COALESCE()
翻译成CASE
表达式一样。)