= null 和 is null;SQL中关于NULL处理的4个陷阱;三值逻辑

一、概述

1、NULL参与的所有的比较和算术运算符(>,=,<,<>,<=,>=,+,-,*,/) 结果为unknown;

2、unknown的逻辑运算(AND、OR、NOT)遵循三值运算的真值表;

3、如果运算结果直接返回用户,使用NULL来标识unknown

4、如果运算结果是作为条件判断真假,那么需要通过三值逻辑进行运算,并最终通过以下映射逻辑确定整体判定

5、{false、unknown} -> false

6、{true} ->true

7、在UNION 或 INTERSECT等集合运算中,NULL 被视为彼此相等。

二、三值逻辑

在逻辑学中的三值逻辑(three-valued,也称为三元,或三价逻辑,有时缩写为3VL)是几个多值逻辑系统中的其中之一。有三种状态来表示真、假和一个表示不确定的第三值;这相对于基础的二元逻辑(比如布尔逻辑,它只提供真假两种状态)。

三值逻辑有三个真值(true、false、unknown),它的AND、OR、NOT运算的真值表如下:
在这里插入图片描述

三、SQL中关于NULL处理的4个陷阱

1、 比较谓词与NULL

null并不能判断表达式为空, 判断表达式为空应该使用is null
goods表有13条数据,其中13条数据的count字段的值是null

select *from goods --14条
错误写法:
select *from goods g where g.count = null --0条

正确写法:
select *from goods g where g.count is null --13条

错误原因:
原因是:g.count= null的结果是unknown;然后unknown判断真假为false。

g.count = null -> unknown -> false;

2、Case When与NULL

错误写法:
case expr when nulll then ‘值1’
并不能判断字段expr为null时, 给字段exper赋值为’值1’

正确写法:
case when expr is null then ‘值1’

select c_name, case when c_nationcode = ‘us’ then ‘USA’
when c_nationcode = ‘cn’ then ‘China’
when c_nationcode is null then ‘China’
else ‘Others’ end
from customer

3、 NOT IN 与NULL

NOT IN 子查询谓词,如果子查询结果集有空值,NOT IN谓词总为假 ,即sql不返回数据
例如goods表里数据的count字段只有1条数据是有值等于1,其余数据count字段值都是NULL。 worker表有9条数据,只有1条数据和goods表关联,worker.id = goods.count。

错误写法:
–查出0条
select *from worker where id not in (select count from goods)
因为使用NOT IN 时,子查询的结果集里有空值,这个SQL永远返回为空。

正确写法1:在子查询里加上非空限制
–查出8条
select *from worker where id not in (select count from goods where count is not null)

正确写法2:将NOT IN子查询改写为not exists子查询
–查出8条
select * from worker where not exists (select count from goods where count = worker.id)

4、修饰符ALL与NULL

ALL修饰的子查询谓词,如果子查询的结果集中有空值,则该谓词总为false。
假设通过下面的sql来获取订单系统关闭后注册的用户。
错误写法:
select * from customer where c_regdate > all(select o_orderdate from orders)

和上面的NOT IN类似的,由于子查询的结果中存在NULL,这个sql不会返回预期的结果。ALL 运算实际执行时也是与返回的结果集一一比较,然后进行AND的运算,最终结果unknown。而unknown作为条件进行评估是,结果为false.

正确写法1:在子查询里加上非空限制
select * from customer where c_regdate > all(select o_orderdate from orders where o_orderdate is not null)

正确写法2:
将expr > all或expr >= all改写为聚集函数 expr > (select max()…)(如果expr < all或expr <= all,则改写为expr < (select min() …)、
select * from customer where c_regdate > (select max(o_custkey) from orders)

–错误写法:0条
select *from worker where id > all (select count from goods)

–正确写法:8条
select *from worker where id > all (select count from goods where count is not null) --8条
select *from worker where id > all (select max(count) from goods) --8条

select *from worker where id <= all (select max(count) from goods) --1条

select *from worker where id <= all (select min(count) from goods) --1条
select *from worker where id > all (select min(count) from goods) --8条
注意:为了sql 优化不建议用聚集函数。
在这里插入图片描述
在这里插入图片描述

四、总结

1、NULL参与的所有的比较和算术运算符(>,=,<,<>,<=,>=,+,-,*,/) 结果为unknown
2、unknown的逻辑运算(AND、OR、NOT)遵循三值运算的真值表
3、如果运算结果直接返回用户,使用NULL来标识unknown
4、如果运算结果是作为条件判断真假,那么需要通过三值逻辑进行运算,并最终通过以下映射逻辑确定整体判定:
5、 {false、unknown} -> false
6、 {true} ->true

五、场景

接收到外部系统传的车辆配置编码保存在订单表的config_code字段里。在本系统订单表config_code 关联车辆配置表的编码字段code, 在车辆配置表查询内外饰颜色,选装等字段。如果外部系统传的车辆配置编码是空值,那么保存在订单表里的这条数据的config_code字段值也是空。用这条订单数据去关联车辆配置表,就什么也查不出来了。不会报错。

例如:
– goods表和worker表关联,w.id = g.count
–goods表14条数据,13条数据的count字段值为null, 1条数据的count = 1
–worker表9条数据, 数据的id字段值都正常
– 查询结果14条 = goods表和worker表关联的数据量1条 + goods表和worker表没关联的数据量13条
– 查询结果的总数据量=从表关联上主表的数据量+主表没关联上从表的数据量
select g.“name”,g.count ,w.work_number,w.id as wid from
goods g
left join worker w on w.id = g.count

在这里插入图片描述

参考文章:https://zhuanlan.zhihu.com/p/560941002

相关推荐

  1. mysql 索引null关系

    2024-07-19 04:58:02       29 阅读
  2. Mysqlnull处理

    2024-07-19 04:58:02       26 阅读
  3. SQL进阶 | 逻辑NULL

    2024-07-19 04:58:02       55 阅读
  4. MySQLNULL问题

    2024-07-19 04:58:02       54 阅读
  5. mysql null区别

    2024-07-19 04:58:02       34 阅读
  6. MySQLNULL与空

    2024-07-19 04:58:02       49 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-07-19 04:58:02       67 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-07-19 04:58:02       71 阅读
  3. 在Django里面运行非项目文件

    2024-07-19 04:58:02       58 阅读
  4. Python语言-面向对象

    2024-07-19 04:58:02       69 阅读

热门阅读

  1. 数据解析的四种方式

    2024-07-19 04:58:02       14 阅读
  2. 任务调度与执行的C++线程池

    2024-07-19 04:58:02       21 阅读
  3. Android EDLA项目 5G热点打开失败分析

    2024-07-19 04:58:02       22 阅读
  4. PHP 调用 1688 详情 API 接口的实战攻略

    2024-07-19 04:58:02       20 阅读
  5. 数据挖掘新技能:Python爬虫编程指南

    2024-07-19 04:58:02       20 阅读
  6. git-常用基础指令

    2024-07-19 04:58:02       17 阅读
  7. unity C#执行bat文件

    2024-07-19 04:58:02       18 阅读
  8. C语言 分割链表

    2024-07-19 04:58:02       20 阅读
  9. 如何使用Python实现一个简单的Web服务器

    2024-07-19 04:58:02       17 阅读
  10. 微服务重启优化kafka+EurekaNotificationServerListUpdater

    2024-07-19 04:58:02       20 阅读