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
即使最后一个条件将其评估为“否”,结果仍为“是”。一旦找到第一个TRUE条件,它似乎就会退出。有人可以确认是否是这种情况吗。
#1 楼
•返回结果为TRUE的第一个input_expression = when_expression的result_expression。参考
http://msdn.microsoft.com/zh-cn/library/ms181765.aspx
这是标准的SQL行为:
CASE
表达式的计算结果为第一个真实条件。 如果没有真实条件,则求和为
ELSE
部分。 如果没有真实条件,没有
ELSE
零件,则求值为NULL
。评论
我只是想确保如果我有3个条件条件都可以评估为true的情况,我只希望执行第一个条件评估为true的任务,而不要执行其他两个任务条件(即使它们也评估为true) )。从我的问题中的示例查询来看,情况确实如此。我只是想确认一下。我也希望SQL从上到下读取CASE条件。谢谢!
– Juan Velez
13年5月30日在13:42
#2 楼
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小提琴)
评论
怎么样?:SQL-Fiddle
–超立方体ᵀᴹ
13年5月30日在13:24
小提琴是关于SQL-Server的。这是亚伦的答案:即使第一个参数不为NULL,SQL Server也会读取所有COALESCE函数吗?
–超立方体ᵀᴹ
13年5月30日在13:39
@ypercube这是非常有趣的行为。它正在评估将在else部分中运行的代码,但似乎会忽略它,这取决于存在其他WHEN表达式以及除零是否在MIN内。参见sqlfiddle.com/#!6/d41d8/4468
–雷·里菲尔(Leigh Riffel)
13年5月30日在13:52
@ypercube现在,我已经阅读了您发布的一些链接,您是否会说有足够多的案例说明SQL Server是否进行短路评估的答案通常是-?
–雷·里菲尔(Leigh Riffel)
13年5月30日在13:58
是的,我同意“通常”。正如亚伦(Aaron)指出的那样,一项测试足以证明“案例总是短路”。但是通常是这样。
–超立方体ᵀᴹ
2013年5月30日14:19
#3 楼
看来MS SQL Server也使用短路评估。在以下测试中,我有3个测试。第一个始终为true,第二个始终不引用表而失败,而第三个仅当考虑到数据时失败。
在此特定运行中,两行都成功返回。如果我注释掉第一个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
#4 楼
在MySQL中,它将在第一个true选项上退出case语句。如果您可能有多个真值,则希望在顺序的前面放置首选答案。评论
问题是关于SQL Server。
–詹姆斯·安德森(James Anderson)
17年4月15日在8:26
#5 楼
如果在WHERE
条件中使用的case语句以及when语句的第一个case涉及评估表中的列值,并且表中的第一行不满足此条件,则case语句将在when语句时转到下一个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
评论
密切相关:即使第一个参数不为NULL,SQL Server也会读取所有COALESCE函数吗? (因为COALESCE()转换为CASE表达式。)