如果子查询没有返回结果,为啥“= ALL(子查询)”评估为真?
Posted
技术标签:
【中文标题】如果子查询没有返回结果,为啥“= ALL(子查询)”评估为真?【英文标题】:Why does "= ALL (subquery)" evaluate to true if the subquery returnes no results?如果子查询没有返回结果,为什么“= ALL(子查询)”评估为真? 【发布时间】:2021-12-09 10:15:18 【问题描述】:如果子查询没有返回任何结果,我希望“= ALL (subquery)”的计算结果为 false。
但是在测试中我发现情况并非如此:
--put one record in #Orders
SELECT 1 AS 'OrderID'
INTO #Orders;
--put one record in #OrderLines
SELECT
1 AS 'OrderID'
,1 AS 'OrderLineID'
,3 AS 'Quantity'
INTO #OrderLines;
--as expected this returns the record in #Orders
SELECT *
FROM #Orders
WHERE 3 = ALL
(
SELECT Quantity
FROM #OrderLines
);
--now delete the record in #OrderLines
DELETE FROM #OrderLines;
--this still returns the record from #Orders even though the subquery returns no results
SELECT *
FROM #Orders
WHERE 3 = ALL
(
SELECT Quantity
FROM #OrderLines
);
最终select语句的执行计划:https://www.brentozar.com/pastetheplan/?id=H1jQ2YgIK
测试日期:
Microsoft SQL Server 2017 (RTM-CU20) (KB4541283) - 14.0.3294.2 (X64) Microsoft SQL Server 2017 (RTM-CU25) (KB5003830) - 14.0.3401.7 (X64)在搜索时,我发现非官方来源说如果子查询没有返回结果,则“= ALL(子查询)”的计算结果为 true:
“ALL 必须以比较运算符开头,如果查询没有返回任何行,则计算结果为 TRUE”https://dotnettutorials.net/lesson/all-operator-sql-server/
“ALL 必须以比较运算符开头,如果查询没有返回任何行,则计算结果为 TRUE”https://www.w3resource.com/sql/special-operators/sql_all.php
但我在官方文档 (https://docs.microsoft.com/en-us/sql/t-sql/language-elements/all-transact-sql?view=sql-server-ver15) 中没有看到任何支持该想法的内容,实际上它似乎对此提出异议:"ALL 要求 scalar_expression 与返回的每个值进行正比较通过子查询"
问题
-
如果子查询未返回任何结果,SQL Server 中的预期行为是否会将 ALL 评估为真?
如果#1 的答案是“是”:
它是否记录在某处?
这种行为的解释是什么?在上面的代码示例中,3 没有与没有结果进行正面比较,因此查询应该返回结果似乎非常不直观
感谢您的帮助和见解。
【问题讨论】:
我怀疑这是文档中的遗漏;如果是这样,您最好通过在文档的 GitHub 上提出问题来查询事实。不过,我必须承认,ALL
很少使用。大多数人更喜欢使用NOT EXISTS
之类的东西。
您引用的 document 声明:“结果值当所有对 (scalar_expression,x) 的比较指定为 TRUE 时返回 TRUE,当x 是单列集中的值。否则返回 FALSE。魔鬼的拥护者:如果没有返回行,那么比较 not TRUE 是哪一行?广告中的真相:Microsoft PowersHell。
我了解只有在子查询中至少有一个值与比较不匹配时,ALL 才会返回 false。所以,是的,我认为这是预期的行为。
关于这种行为的解释,请看***.com/a/2195428/11683。
这能回答你的问题吗? ALL operator VS Any on an empty query
【参考方案1】:
转述documentation:
...如果子查询的某些值不符合表达式的条件,
scalar_expression = ALL (subquery)
将评估为 FALSE。
这很微妙,但是如果 some 值确实不满足条件,则意图似乎是返回 false,否则返回 true。在没有值的边缘情况下,没有不满足条件的值,所以返回true。
导致可能令人惊讶的结果的“问题”是单词“some”,它暗示存在。如果不存在值,则不可能有“某些”值是假的,所以它是真的。
您可以说它基于双重否定逻辑,其中边缘情况恰好落在结果的意外一半。
顺便说一句,我在职业生涯中编写了大量 SQL,但从未使用过这个关键字,也没有见过它使用过。
建议:不要使用。
【讨论】:
以上是关于如果子查询没有返回结果,为啥“= ALL(子查询)”评估为真?的主要内容,如果未能解决你的问题,请参考以下文章