SQL计划编译和真值表

J.T*_*.T. 7 sql sql-server null left-join

如果我有 NOT ( 1 <> 1 AND NULL <> 1 )

我可以看到SQL将其转化为执行计划XML: ( 1 = 1 OR NULL = 1)

如果你真的要评估前面的表达式,那么True AND Null它将是Null并将消除该行.但是,由于OR,编译后的表达式可以返回一行.

我可以假设这种类型的编译始终保证会发生吗?SQL Server永远不会尝试将复杂的逻辑推进到编译计划中?有关于此的一些文件吗?

这篇文章非常有用,但我只是错过了一个难题:https: //www.simple-talk.com/sql/learn-sql-server/sql-and-the-snare-of-three-valued -逻辑/

这是一个SQL示例

SELECT 1
FROM T T
    LEFT JOIN T2 T2 --t2 has zero rows
        ON T.id = t2.t_id
WHERE NOT ( T.id <> 99 AND T2.id <> 99 )
Run Code Online (Sandbox Code Playgroud)

根据我的SQL经验,我知道在正常情况下(没有短路评估)T2.id <> 99有效地将左连接转换为内连接.这是我的行为最初预期.当这个过滤器实际工作时我很惊讶.

phi*_*pxy 4

TL;DR “编译结果”不是一个有用的概念。重要的是“指定的结果”——由语言定义指定。DBMS 必须使语句按照您编写的方式运行。

您的链接中 AND 的真相表是错误的。在 SQL 中,AND 与 False 始终为 False,OR 与 True 始终为 True。


SQL 中的比较返回 True、False 或 Unknown。未知可能是由于与未知上的 NULL 或 3VL 逻辑连接词(AND/OR/NOT 等)进行比较而产生的。“NULL”不是字面意思。True、False 和 Unknown 是 SQL 标准中带有(各种)文字的值,但在大多数 DBMS 中并非如此。(Unknown 可以返回为 NULL。)IS 不是比较;而是比较。IS NULL 和 IS NOT NULL 是一元 3V1 逻辑连接词,以 TRUE、FALSE 和 UNKNOWN 命名的类似连接词也是如此。它们总是返回 True 或 False。

True AND Null将为 Null 并且会消除该行。但是,由于 OR,编译的表达式可能会返回一行。

不。您链接中 AND 的真相表是错误的。在 SQL 中,AND 与 False 始终为 False,OR 与 True 始终为 True。因此,从 1 <> 1 的 False 的 AND 得出的 AND 始终为 False,并且从 1 = 1 得出的 OR 始终为 True。无论其他比较返回什么(True、False 或未知)。如果您使用(正确的)SQL 真值表来处理这两个表达式,它们总是给出相同的结果 True。

在 SQL 中重写条件时必须非常小心。可以NOT (E1 *comparison* E2)通过E1 *NOT-comparison* E2NOT (E IS ?)和互换E IS NOT ?。如果没有值是 NULL,则可以使用标准逻辑恒等式/规则安全地重写表达式。人们还可以安全地将重写规则应用于

    (E1 *comparison* E2)
AND E1 IS NOT NULL AND E2 IS NOT NULL
Run Code Online (Sandbox Code Playgroud)

另请注意,您必须正确使用“未知”最终结果,其中包括不匹配 WHERE 但不因约束失败。

SELECT 1
FROM T T
    LEFT JOIN T2 T2 --t2 has zero rows
        ON T.id = t2.t_id
WHERE NOT ( T.id <> 99 AND T2.id <> 99 )
Run Code Online (Sandbox Code Playgroud)

LEFT JOIN 返回 INNER JOIN 的行加上由 T2 列 NULL 扩展的 T 的不匹配行。(如果 T2 为空,则 INNER JOIN 为空,并且 T 的所有行都不匹配。)所有扩展行的 T2.id <> 99 未知,因为 T2.id 为 NULL。对于 T.id = 99,AND 为 False,NOT 为 True;WHERE 返回所有行。对于 T1.id 任何其他整数或 NULL,AND 将为 Unknown,NOT 将为 Unknown;WHERE 不返回任何行。

(SQL 中没有条件的“短路”评估。连接词的每个参数都必须定义。)