是否对SQL WHERE子句进行了短路评估?

Gre*_*ean 135 sql short-circuiting

例如:

SELECT * 
FROM Table t 
WHERE @key IS NULL OR (@key IS NOT NULL AND @key = t.Key) 
Run Code Online (Sandbox Code Playgroud)

如果@key IS NULL的计算结果为true,那么@key IS是否为NULL并且@key = t.Key是否已计算?

如果不是,为什么不呢?

如果是,是否有保证?它是ANSI SQL的一部分还是特定于数据库?

如果是数据库特定的,SqlServer?甲骨文?MySQL的?

参考:短路评估

小智 70

ANSI SQL Draft 2003 5WD-01-Framework-2003-09.pdf

6.3.3.3规则评估顺序

[...]

如果优先级不是由格式或括号确定的,则表达式的有效评估通常从左到右执行.但是, 依赖于实现是否实际上是从左到右计算表达式,特别是当操作数或运算符可能导致条件被引发时,或者如果可以在不完全评估表达式的所有部分的情况下确定表达式的结果.

  • SQL是一种声明性语言,它基本上表达了计算的逻辑而没有描述其控制流程; 这与短路评估的必要风格及其后果相矛盾. (6认同)
  • 实现依赖?大.很高兴知道.至少`CASE`是短路的. (4认同)
  • 这是不是意味着表达式评估不明确?"(0 = 0 OR NULL)",如果计算所有项,则始终为NULL,但如果从左到右进行评估并且短路,则始终为true. (3认同)

小智 57

从上面来看,短路并不是真的可用.

如果您需要,我建议一个Case声明:

Where Case when Expr1 then Expr2 else Expr3 end = desiredResult
Run Code Online (Sandbox Code Playgroud)

Expr1总是评估,但只有一个Expr2Expr3将每行进行评估.

  • 这取决于我假设的RDBMS实现.至少对于SQL Server,至少存在一个异常,记录为不显示此行为(即短路); cf [CASE(Transact-SQL) - 备注](https://msdn.microsoft.com/en-us/library/ms181765.aspx#Anchor_3).我在[这个答案]中引用了这个案例(http://stackoverflow.com/a/35848730/243373)我给出了问题*Sql - WHERE条件的明确顺序?*. (3认同)

dkr*_*etz 19

我认为这是我写它的情况之一,好像它没有短路,原因有三个.

  1. 因为对于MSSQL来说,通过在显而易见的位置查看BOL无法解决问题,所以对我而言,这使得它在规范上变得模棱两可.

  2. 因为至少我知道我的代码会起作用.更重要的是,那些追随我的人也是如此,所以我不会让他们一遍又一遍地担心同样的问题.

  3. 我经常写几个DBMS产品,如果我能轻松解决这些问题,我不想记住这些差异.

  • 很棒的建议.它没有回答这个问题,但这是一个非常务实的观点.所以+1 (4认同)

Meh*_*ras 12

我不相信SQL Server(2005)中的短路是有保障的.SQL Server通过其优化算法运行您的查询,该算法考虑了很多事情(索引,统计信息,表大小,资源等)以提出有效的执行计划.在此评估之后,您无法确定您的短路逻辑是否得到保证.

我前一段时间遇到了同样的问题,我的研究确实没有给出一个明确的答案.你可以编写一个小的查询来给你一个证明它有效的证据,但是你可以确定随着数据库负载的增加,表变得更大,并且数据库中的事情得到优化和改变,结论将是保持.我不能因此而谨慎,并在WHERE子句中使用CASE来确保短路.


Log*_*ind 7

您必须记住数据库的工作方式.给定参数化查询,db基于该查询构建执行计划,而不使用参数值.无论实际提供的值是什么,每次运行查询时都会使用此查询.具有特定值的查询短路是否与执行计划无关.

  • 执行速度很重要! (6认同)

p.c*_*ell 5

我通常将其用于可选参数。这和短路一样吗?

SELECT  [blah]
FROM    Emp
WHERE  ((@EmpID = -1) OR (@EmpID = EmpID))
Run Code Online (Sandbox Code Playgroud)

这使我可以选择传递 -1 或其他值来解释属性的可选检查。有时这涉及连接多个表,或者最好是一个视图。

非常方便,但不完全确定它给数据库引擎带来的额外工作。