在编程语言中,逻辑表达式的值只有两种:TRUE和FALSE,而在数据库中却并非如此。
今天在'MYSQL技术内幕'一书中发现了相关的知识:
“关系数据库中起逻辑表达式作用的并非只有两种,还有一种称为三值逻辑的表达式”,这里的三值逻辑表达式指的就是UNKNOW。当在进行真假状态判断而又不能明确知道该状态是TRUE还是FALSE时,那么它就属于UNKNOW状态。那这样理解也是可以的:它既有可能表示TRUE又有可能表示FALSE--连表示什么状态也不知道。所以我们在数据库应用当中涉及到与NULL值进行比较的时候就要留意一点。
这是“内幕”中的例子:
(1)mysql> select 0=null;
+--------+
| 0=null |
+--------+
| NULL |
+--------+
1 row in set
(2)mysql> select null=null;
+-----------+
| null=null |
+-----------+
| NULL |
+-----------+
1 row in set
(3)mysql> select not null = null;
+-----------------+
| not null = null |
+-----------------+
| NULL |
+-----------------+
1 row in set
上面例子中的结果都是NULL,这里我们应当将NULL看作是UNKNOWN,即表示未知的。有两种情形认为两个NULL是相等的:
(1)GROUP BY 子句将所有NULL值分到一组。
(2)ORDER BY 子句将所有NULL值排列到一组。
这个是不相等的一种情形:
在ON过滤条件下的NULL值比较,比较结果为UNKNOWN,会被视为FALSE,即两个NULL值并不相同。
“内幕”中的另一个地方也提到了NULL与三值逻辑的关系就是EXISTS与IN的区别。“在对三值逻辑的判断上EXISTS总是返回TRUE或FALSE,而对于IN,还有另一种可能就是UNKNOWN。”因而对于包含了NULL值的比较过程中NOT IN 总是返回NOT TRUE 和 NOT UNKNOWN,也就是FALSE和UNKNOW。但对于NOT EXISTS 其结果只有TRUE和FALSE,这是二者很大区别的一个地方。
在实际的应用中,如果数据中不含有NULL值,那么NOT EXISTS与NOT IN 除了在底层的执行计划有细微差别外二者的查询结果是一致。若数据中含有NULL值则二者的差别就非常明显了:NOT EXISTS依然返回与不含有NULL值相同的数据,而NOT IN会返回空集合,如果想要排除NULL值对NOT IN 的影响,使用先过滤掉NULL值:WHERE<WHERE-CONDITION IS NOT NULL>。