sql-server - MS-SQL AND/OR 是否有条件(执行短路评估)?

标签 sql-server stored-procedures

我正在创建一个存储过程(简化)

create procedure sp_mysp @p1 bit AS
if (@p1 = 1 AND EXISTS(select  * from mytable1))
BEGIN....END
ELSE IF (@p = 0 AMD EXISTS(select * from mytable2))
BEGIN....END

所以问题是,如果@p1 等于 1,SQL 会一直检查 mytable1 中的数据还是只检查 mytable1 中的数据

(类似于c#中的&&)

最佳答案

无法保证这种行为。
expr1 AND expr2 未发生短路评估的示例是

SET STATISTICS IO ON

IF EXISTS(SELECT COUNT(*) FROM master..spt_monitor HAVING COUNT(*)=2)  
AND EXISTS (SELECT COUNT(*) FROM master..spt_values HAVING COUNT(*)=1)
PRINT 'Y'
EXISTS(SELECT COUNT(*) FROM master..spt_monitor HAVING COUNT(*)=2)false (意味着 And -ed 表达式必须是 False )但 IO 结果显示仍然评估了第二个条件。
Table 'spt_values'. Scan count 1, logical reads 14, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'spt_monitor'. Scan count 1, logical reads 1, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

不过,SQL Server 可以做到这一点。我在测试中看到了这个
SET STATISTICS IO ON

DECLARE @p1 BIT = NULL

IF ( @p1 = 1
     AND EXISTS(SELECT *
                FROM   master..spt_values) )
  PRINT '1'

ELSE IF ( @p1 = 0
     AND EXISTS(SELECT *
                FROM   master..spt_values) )
  PRINT '2'

输出是
Table 'Worktable'. Scan count 0, logical reads 0, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

(1 row(s) affected)
Table 'Worktable'. Scan count 0, logical reads 0, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

(1 row(s) affected)

显示 spt_values从未被访问过。

这是通过执行计划中的传递谓词条件实现的。有一些关于那些here的信息.

If the passthru predicate evaluates to true, the join returns the row .... If the passthru predicate evaluates to false, the join proceeds normally



enter image description here

关于sql-server - MS-SQL AND/OR 是否有条件(执行短路评估)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46134872/

相关文章:

sql - 无法创建索引 View ,因为我引用了派生表

mysql - 使用变量设置mysql INNODB AUTO_INCRMENT表值

MySQL - 跳转到存储过程中的 "foo:Begin"

sqlite - 创建存储过程和 SQLite?

c# - 通过组合两列来选择不同的项目,其中第三列的值为 max-LINQ

sql-server - 报表生成器/SSRS 和 RDL - HTML <img> 支持吗?

sql - 如何在 MSSQL 中声明 VARCHAR 变量

sql-server - 基于参数标志定义动态 IN 子句的正确方法是什么?

使用游标和临时表时的 MySQL 存储过程性能问题

sql-server - 有没有办法根据变量将 WHERE 子句中的比较设置为 IS NULL 或 IS NOT NULL