为什么 `NOT(NULL=NULL)` 是假的?

Why is `NOT(NULL=NULL)` false?

(NULL = NULL)false。美好的。记为"NULL is defined not to be equal to anything".

(NULL = NULL)false。呃……好吧,很公平。记为"NULL represents an undefined value, so you never know whether it is or isn't equal to something else".

NOT(NULL = NULL)false。等等,什么!?

说真的,这怎么可能有效? "NOT()" 运算符的行为如何依赖于正在评估的表达式的细节!? 所有 SQL 系统都这样做吗?


演示查询:

SELECT '"1 & 1"',
       '"1 = 1" is ' + (CASE WHEN (1=1) THEN 'true' ELSE 'false' END) AS 'a=b',
       '"1 <> 1" is ' + (CASE WHEN (1<>1) THEN 'true' ELSE 'false' END) AS 'a<>b',
       '"NOT(1=1)" is ' + (CASE WHEN NOT(1=1) THEN 'true' ELSE 'false' END) AS 'NOT(a=b)',
       '"NOT(1<>1)" is ' + (CASE WHEN NOT(1<>1) THEN 'true' ELSE 'false' END) AS 'NOT(a<>b)'
UNION
SELECT '"1 & 2"',
       '"1 = 2" is ' + (CASE WHEN (1=2) THEN 'true' ELSE 'false' END)AS 'a=b',
       '"1 <> 2" is ' + (CASE WHEN (1<>2) THEN 'true' ELSE 'false' END)AS 'a<>b',
       '"NOT(1=2)" is ' + (CASE WHEN NOT(1=2) THEN 'true' ELSE 'false' END)AS 'NOT(a=b)',
       '"NOT(1<>2)" is ' + (CASE WHEN NOT(1<>2) THEN 'true' ELSE 'false' END) AS 'NOT(a<>b)'
UNION
SELECT '"NULL & 1"',
       '"NULL = 1" is ' + (CASE WHEN (NULL=1) THEN 'true' ELSE 'false' END) AS 'a=b',
       '"NULL <> 1" is ' + (CASE WHEN (NULL<>1) THEN 'true' ELSE 'false' END) AS 'a<>b',
       '"NOT(NULL=1)" is ' + (CASE WHEN NOT(NULL=1) THEN 'true' ELSE 'false' END) AS 'NOT(a=b)',
       '"NOT(NULL<>1)" is ' + (CASE WHEN NOT(NULL<>1) THEN 'true' ELSE 'false' END) AS 'NOT(a<>b)'
UNION
SELECT '"NULL & NULL"',
       '"NULL = NULL" is ' + (CASE WHEN (NULL=NULL) THEN 'true' ELSE 'false' END)AS 'a=b',
       '"NULL <> NULL" is ' + (CASE WHEN (NULL<>NULL) THEN 'true' ELSE 'false' END)AS 'a<>b',
       '"NOT(NULL=NULL)" is ' + (CASE WHEN NOT(NULL=NULL) THEN 'true' ELSE 'false' END)AS 'NOT(a=b)',
       '"NOT(NULL<>NULL)" is ' + (CASE WHEN NOT(NULL<>NULL) THEN 'true' ELSE 'false' END) AS 'NOT(a<>b)'

three-valued logic (3VL)定义逻辑运算符为:

+---------+---------+---------+---------+---------+
| p       | q       | p OR q  | p AND q | p = q   |
+---------+---------+---------+---------+---------+
| True    | Unknown | True    | Unknown | Unknown |
| False   | Unknown | Unknown | False   | Unknown |
| Unknown | True    | True    | Unknown | Unknown |
| Unknown | False   | Unknown | False   | Unknown |
| Unknown | Unknown | Unknown | Unknown | Unknown |
+---------+---------+---------+---------+---------+

NOT行为具有以下事实table:

+---------+---------+
| p       | NOT p   |
+---------+---------+
| True    | False   |
| False   | True    |
| Unknown | Unknown |
+---------+---------+

因此,在表达式 NOT(NULL = NULL) 中,您得到:

NULL = NULL -> Unknown
NOT(Unknown) -> Unknown

您的案例条件总是表现得像 未满足,因为您的表达式计算结果为未知,即 既非真又非假

有关 SQL 服务器处理空值的方式的更多信息,请查看 Why does NULL = NULL evaluate to false in SQL server

原因是NULL是为了表示没有值或未知值。 SQL 在选择这些含义之一时并不一致,但在大多数情况下 NULL 表现得像一个未知值。

NULL = NULL returns NULL 因为,如果比较两个未知值,结果是未知的。它们可以相同也可以不同。

有办法对付NULL。最常见的是 IS NULLIS NOT NULL 语法。但是您也可以以 NULL 安全的方式比较两个值。在这种情况下,要使用的语法取决于您使用的 DBMS。更多详情 here.