知识卡片
NULL与三值逻辑:逻辑正确与现实正确的分离
内容
NULL被解释为”值未知”后,任何一个比较元为NULL的比较表达式结果不再是TRUE或
FALSE,而是第三个真值UNKNOWN——这就是三值逻辑(3VL)的来源(对照的是关系
模型基于的常规二值逻辑2VL)。NOT/AND/OR的3VL真值表都有一条共同规律:只要
涉及UNKNOWN,结果往往也变成UNKNOWN(除非另一个操作数的值本身已经能单独
决定结果,比如TRUE OR UNKNOWN仍是TRUE)。禁止NULL最有力的依据是:存在
按三值逻辑运算完全”正确”、但在现实世界里却给出错误答案的布尔表达式。书中
给出一个具体证明:零件P1的CITY是NULL(代表”存在真实城市但未知”),查询
“城市不同或零件城市不是Paris”的WHERE子句(S.CITY<>P.CITY) OR (P.CITY<>'Paris')
对这条数据求值得到UNKNOWN OR UNKNOWN,化简为UNKNOWN,SQL只挑选值为TRUE的行,
于是这行被漏掉;但作者证明不论P1真实城市c到底是不是Paris,这个表达式在现实
世界里恒为TRUE——分类讨论c=Paris和c≠Paris两种情况,表达式的两个分支总有一个
恒为TRUE。另一个更直接的例子是WHERE CITY=CITY——现实世界的正确答案显然是
所有出现在表里的零件编号,但SQL对CITY是NULL的行求值得到UNKNOWN,同样一个
都不返回。这两个例子共同证明:一旦数据库存在NULL,某些查询的3VL逻辑结果和
现实世界的真实答案会彻底脱节,而且用户无法预先知道到底哪些查询会出这种问题,
结果是数据库给出的任何答案都变得不可信任。
参考来源
- 位置:《SQL与关系数据库理论——如何编写健壮的SQL代码》第4章"不要重复,不要
null"4.4节"null有什么毛病"(源文件:OEBPS/text00046.html)
- 结论依据:原文明确"任何其中一个比较元为null的比较式都会得到真值UNKNOWN……
存在布尔表达式(因此也存在查询),其结果依据三值逻辑是正确的,但在现实世界中
是不正确的……此布尔表达式在现实世界中总是为真。所以,查询也应该不管null到底
代表什么值都返回(S1,P1)……如果数据库中有null,一些查询就会得到错误答案。
而且,你无从知晓到底哪个查询会得到错误的答案……你永远不能相信从包含null的
数据库中得到的答案"。
- 原始内容:存在布尔表达式(因此也存在查询),其结果依据三值逻辑是正确的,但
在现实世界中是不正确的……如果数据库中有null,一些查询就会得到错误答案。而且,
你无从知晓到底哪个查询会得到错误的答案,而哪些又不会……你永远不能相信从包含
null的数据库中得到的答案。