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

标签 sql sql-server null logical-operators three-valued-logic

(NULL = NULL)false。美好的。记住“NULL 被定义为不等于任何东西”。

(NULL = NULL)false。呃……好吧,很公平。记住“NULL 表示一个未定义的值,所以你永远不知道它是否等于其他值”。

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 行为具有以下真值表:

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

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

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

您的案例条件总是表现得像未满足,因为您的表达式求值为未知,即既非真也非假

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

关于sql - 为什么 `NOT(NULL=NULL)` 是假的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43321100/

相关文章:

python - Django:分配尚未创建的类的外键

python - SQLAlchemy 根据 JSONB 中的嵌套键进行过滤

sql-server - MS/Transact-SQL 存储过程可以查找自己的名称吗?

php - 使用 PDO 插入 NULL 而不是空字符串

java - 'null' 应该被视为数字吗? ...字母数字?

Sql Select 使用 CTE 对递归数据进行排序

mysql - 如何将表连接到 MySQL 中的排名 SELECT 查询?

sql - 如何根据子查询中的计数选择记录数

sql-server - debezium sqlserver 连接器输出数字/小数字段的编码值

php - 检查变量是否为空