我不了解SQL Server,因此无法发表意见。
对于某些逻辑运算符L和表达式a L b,没有保证a会在b之前或之后被计算,甚至可能不会同时计算a和b:
表达式求值规则
子表达式的计算顺序未定义。特别地,运算符或函数的输入未必按照从左到右或其他固定顺序进行计算。
此外,如果一个表达式的结果只需计算其中一部分即可确定,则其他子表达式可能根本不需要计算。
[...]
注意,这与某些编程语言中的布尔运算符从左到右的“短路”不同。
因此,在复杂表达式中使用带有副作用的函数是不明智的。在 WHERE
和 HAVING
子句中依赖于副作用或计算顺序尤其危险,因为这些子句在制定执行计划时会被广泛重新处理。
就形如下面的表达式而言:
the_column IS NULL OR the_column < 10
就此而言,不用担心,因为对于所有的n,包括NULL,NULL < n都是NULL;而且,NULL < NULL的结果也是NULL;此外,NULL不是真实的。
null is null or null < 10
这只是一种复杂的说法,表示true或null
,而且无论哪个子表达式先被评估,结果都是true
。
整个“使用CASE”的听起来大多像对我来说是货物崇拜SQL。然而,像大多数货物崇拜主义一样,在货物下面有一个真理核心; 在我从PostgreSQL手册中摘录的第一个段落下面,您会发现以下内容:
When it is essential to force evaluation order, a CASE
construct (see Section 9.16) can be used. For example, this is an untrustworthy way of trying to avoid division by zero in a WHERE
clause:
SELECT ... WHERE x > 0 AND y/x > 1.5;
But this is safe:
SELECT ... WHERE CASE WHEN x > 0 THEN y/x > 1.5 ELSE false END;
因此,如果您需要防范可能会引发异常或产生其他副作用的条件,那么您应该使用 CASE
来控制评估顺序,因为 CASE
是按顺序进行评估的:
每个条件都是返回 boolean
结果的表达式。如果条件的结果为 true,则 CASE
表达式的值为后续的 结果,并且不处理 CASE
表达式的其余部分。如果条件的结果不为 true,则以同样的方式检查任何后续 WHEN 子句。
因此,假设有以下内容:
case when A then Ra
when B then Rb
when C then Rc
...
A
会在B
之前被评估,B
在C
之前被评估,以此类推,并且当一个条件计算为true值时,评估停止。
总之,CASE
短路但AND
和OR
不会短路,因此仅需要在需要保护副作用时使用CASE
。