知识卡片

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的数据库中得到的答案。