三值逻辑和NULL

数据库中并不是只有:true/false 还有一种值叫 ‘不确定(unknown)null’ 不确定会带来一系列的陷阱。

一、对null的判断为何不能是 ‘=’、‘>’、'<' 、'<>'、 一系列的判断呢?

答:首先NULL不是值,它是对不确定的表示。判断运算符是对值进行判断的,对null使用比较运算符最终结果都是unknown,查询不出任何数据。所以说对 ‘null’ 判断只有使用 ‘is null’/'is not null'

 

看下面的知识前,请先记住  在 'and' 语句中 unknown优先级大于true ,在 'or' 语句中 true优先级大于unknown。

      如:现在有值 a=2 、b=5 、c=null

             1:a<b and b>c

             2:a>b or b<c

             3:a<b or b<c

     答案是: 1 unknown· 、2 unknown 、 3  true

 

第一点:在我们现实世界中有这样的一个真命题 :约翰的年龄是20岁,或者不是20岁,二者必居其一。

     select age from demo where age=20 or age<>20

这是现实世界中的二指逻辑,但是在数据库中并行不通。

现有情况 约翰的年龄不明确为 :null  现在的sql语句就变成了:

    1: select age from demo where age=NULL or age<>NULL

    2:select age from demo where age=unknownor age<>unknownor

    之前说过 在 or 中 出现 unknownor ,true优先级最高,但是这里没有true 所以返回数据为空

 

第二点:CASE 表达式和NULL

null 在 case 表达式中的陷阱:

           case age when 1 then 'O' when NULL then 'X' end;

           这句表达中‘X’ 永远都出不来,因为上面语句最终变成 age=null 无法返回ture 所以‘X’ 不会出现。

          可以改写为:

                              case when age=1 then 'O' when age is NULL then 'X' end;

          切记不能把NULL当成值去运算。

第三点:NOT IN() 和 NOT EXISTS() 不是等价的

              首先not in() 是把其中值变成了 and 语句组装 的简写,如 age NOT IN(1,2,3) 最终变成  age<>1 and age<> 2 and age<>3 。若现在把 age NOT IN(1,2,3) 中 3 换为了null 现在 age<>1 and age<> 2 and age<>null  最后不能得出任何结果值。

             NOT EXISTS() 只会返回true和false 所以会避免返回not in()的情况 ,会排出null值返回正确的值

第四点:限定谓词和null

如在A班中找出比B班所有人年龄大的学生。

select  name from A where age> all(select age from B) ,若B表中age都明确(不是NULL)则没毛病,一旦有NULL 则这条sql语句不会返回任何数据。应为最终都把all中的所有 age 用 'and' 连接起来了(select  name from A where age>19 and age>22 and age>null) ,之前说过and 中 对null算数比较 是不会返回值得,所以....明白? 

第五点:限定谓词和极值函数不是等价

首先回到第四点(在A班中找出比B班所有人年龄大的学生。) 另一种写法:

select  name from A where age>(select max(age) from B) 

这就避免了age不明确的情况?(max(age)会排出为age为null的情况再计算),但是,真的是这样吗?

现有一种情况 B 班没有学生!!! 上面的sql语句就变成了这样:select  name from A where age>(null) ,不会返回任何数据。

极值函数在输入为空集(空表)时,会返回null 。

其实在这里我们希望的是为空集时返回A表中所有数据。All() 函数就避免了这样的情况,或者说用COALESCE函数将极值函数返回的NULL值替换成合适的值。

第六点:聚合函数和null

。除count()聚合函数外,其他的所有聚合函数在为空集时返回的都是null 。在sql语句中:

select  name from A where age>(select max(age) from B)  , where 条件后永远是nuknown 不会返回任何数据,这样的情况只有两种方法可以解决:要嘛把null该成具体的值,要么接受null。

 聚合函数的陷阱是由函数自带的,仅仅只靠在列上加 not null 是无法从根本上消除的,因此我们在编写sql时需要多加注意。

 

总结:

         一、NULL不是值

         二、因为NULL不是值,所以不能对其用谓词

         三、对NULL使用谓词的结果是:unknown

         四、unknown 加入sql逻辑运算时,会带来意想不到的后果(最前面标红字体)

最后说明:想要解决NULL带来的问题,最佳方法是在表中添加not null来尽力排出NULL,这样就能回到二值逻辑的世界(虽然不能完全回到二值逻辑)。

 

内容多来自 《SQL进阶教材》,仅做笔记。一部分是自己理解,欢迎指出不对的地方。

 

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值