gpt4 book ai didi

SQL Server 条件流

转载 作者:行者123 更新时间:2023-12-01 16:10:16 24 4
gpt4 key购买 nike

如果我在 IF EXISTS 条件中编写两个 SELECT 语句,并在这些选择查询之间使用 AND 子句,则两个查询都会执行即使第一个 SELECT 返回 false?

IF EXISTS (SELECT....) AND EXISTS(SELECT ....)
BEGIN

END

在这种情况下,SQL Server 引擎是否执行这两个 SQL 语句?

谢谢克里什

最佳答案

我会将测试重写为

IF CASE
WHEN EXISTS (SELECT ...) THEN CASE
WHEN EXISTS (SELECT ...) THEN 1
END
END = 1

这保证了短路as described here但这确实意味着您需要选择最便宜的来预先评估,而不是将其留给优化器。

在我极其有限的测试中,以下内容在测试时似乎成立

1。 存在和存在

EXISTS AND EXISTS 版本似乎是最有问题的。这个chains together some outer semi joins 。在所有情况下,它都没有重新安排测试顺序以尝试先进行更便宜的测试( an issue discussed in the second half of this blog post )。在 IF ... 版本中,如果有的话也不会有任何区别,因为它没有短路。然而,当这个组合谓词被放入 WHERE 子句中时,计划会发生变化,并且它确实短路,因此重新排列可能会有所帮助。

/*All tests are testing "If False And False"*/

IF EXISTS(SELECT COUNT(*) FROM master..spt_monitor HAVING COUNT(*)=2)
AND EXISTS (SELECT COUNT(*) FROM master..spt_values HAVING COUNT(*)=1)
PRINT 'Y'
/*
Table 'spt_values'. Scan count 1, logical reads 9
Table 'spt_monitor'. Scan count 1, logical reads 1
*/

IF EXISTS (SELECT COUNT(*) FROM master..spt_values HAVING COUNT(*)=1)
AND EXISTS(SELECT COUNT(*) FROM master..spt_monitor HAVING COUNT(*)=2)
PRINT 'Y'
/*
Table 'spt_monitor'. Scan count 1, logical reads 1
Table 'spt_values'. Scan count 1, logical reads 9
*/

SELECT 1
WHERE EXISTS(SELECT COUNT(*) FROM master..spt_monitor HAVING COUNT(*)=2)
AND EXISTS (SELECT COUNT(*) FROM master..spt_values HAVING COUNT(*)=1)
/*
Table 'Worktable'. Scan count 0, logical reads 0
Table 'spt_monitor'. Scan count 1, logical reads 1
*/

SELECT 1
WHERE EXISTS (SELECT COUNT(*) FROM master..spt_values HAVING COUNT(*)=1)
AND EXISTS(SELECT COUNT(*) FROM master..spt_monitor HAVING COUNT(*)=2)
/*
Table 'Worktable'. Scan count 0, logical reads 0
Table 'spt_values'. Scan count 1, logical reads 9

*/

所有这些计划看起来都非常相似。 SELECT 1 WHERE ... 版本和 IF ... 版本之间行为存在差异的原因是,对于前一个版本,如果条件为 false,则正确的行为是不返回任何结果,因此它只是链接OUTER SEMI JOINS,如果其中一个为 false,则零行结转到下一行。

但是,IF 版本始终需要返回 1 或零的结果。该计划在其外连接中使用探测列,并在 EXISTS 测试未通过时将其设置为 false(而不是简单地丢弃该行)。这意味着总是有 1 行输入到下一个 Join 并且它总是被执行。

CASE 版本具有非常相似的计划,但它使用 PASSTHRU 谓词,如果前面的 THEN 则使用该谓词跳过 JOIN 的执行> 不满足条件。我不确定为什么组合的 AND 不会使用相同的方法。

2。 存在还是存在

EXISTS OR EXISTS 版本使用串联 (UNION ALL) 运算符作为外部半连接的内部输入。这种安排意味着,一旦返回第一个行,它就可以停止从内侧请求行(即,它可以有效地短路)。所有 4 个查询都以相同的计划结束,其中首先评估更便宜的谓词。

/*All tests are testing "If True Or True"*/

IF EXISTS(SELECT COUNT(*) FROM master..spt_monitor HAVING COUNT(*)=1)
OR EXISTS (SELECT COUNT(*) FROM master..spt_values HAVING COUNT(*)<>1)
PRINT 'Y'
/*
Table 'Worktable'. Scan count 0, logical reads 0
Table 'spt_monitor'. Scan count 1, logical reads 1
*/

IF EXISTS (SELECT COUNT(*) FROM master..spt_values HAVING COUNT(*)<>1)
OR EXISTS(SELECT COUNT(*) FROM master..spt_monitor HAVING COUNT(*)= 1)
PRINT 'Y'
/*
Table 'Worktable'. Scan count 0, logical reads 0
Table 'spt_monitor'. Scan count 1, logical reads 1
*/

SELECT 1
WHERE EXISTS(SELECT COUNT(*) FROM master..spt_monitor HAVING COUNT(*)= 1)
OR EXISTS (SELECT COUNT(*) FROM master..spt_values HAVING COUNT(*)<>1)
/*
Table 'Worktable'. Scan count 0, logical reads 0
Table 'spt_monitor'. Scan count 1, logical reads 1
*/

SELECT 1
WHERE EXISTS (SELECT COUNT(*) FROM master..spt_values HAVING COUNT(*)<>1)
OR EXISTS(SELECT COUNT(*) FROM master..spt_monitor HAVING COUNT(*)=1)
/*
Table 'Worktable'. Scan count 0, logical reads 0
Table 'spt_monitor'. Scan count 1, logical reads 1
*/

3。添加 ELSE

我确实想到尝试德摩根定律,将 AND 转换为 OR,看看这是否有任何区别。转换第一个查询给出

IF NOT ((NOT EXISTS(SELECT COUNT(*) FROM master..spt_monitor HAVING COUNT(*)=2)  
OR NOT EXISTS (SELECT COUNT(*) FROM master..spt_values HAVING COUNT(*)=1)))
PRINT 'Y'
ELSE
PRINT 'N'
/*
Table 'spt_monitor'. Scan count 1, logical reads 1
Table 'spt_values'. Scan count 1, logical reads 9
*/

所以这对短路行为仍然没有任何影响。但是,如果您删除 NOT 并颠倒 IF ... ELSE 条件的顺序,它现在短路!

IF (NOT EXISTS(SELECT COUNT(*) FROM master..spt_monitor HAVING COUNT(*)=2)  
OR NOT EXISTS (SELECT COUNT(*) FROM master..spt_values HAVING COUNT(*)=1))
PRINT 'N'
ELSE
PRINT 'Y'
/*
Table 'Worktable'. Scan count 0, logical reads 0
Table 'spt_monitor'. Scan count 1, logical reads 1
*/

关于SQL Server 条件流,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5542927/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com