我正在创建一个存储过程(简化)
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
所以问题是,SQL总是会检查mytable1中的数据,还是只检查mytable1中的数据,如果@ p1等于1
(类似&& in c#)
答案 0 :(得分:6)
无法保证此行为。
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的信息。
如果passthru谓词的计算结果为true,则join返回该行 ....如果passthru 谓词评估为false,连接正常进行
答案 1 :(得分:2)
短路is not guaranteed in SQL Server TSQL。
数据库尝试优化查询,并且可以以与查询中观察到的顺序不同的顺序执行表达式/操作。您可以查看a blog entry from Microsoft,一组 experiments in SQL Server 2005以及OR behavior in SQL server上的另一个讨论。