欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

你知道SQL的中NULL,该怎么处理吗?

程序员文章站 2022-06-07 16:13:39
...

在使用数据库做业务开发时,经常会遇到关键字"null";那null""有什么区别呢?null通常用在什么地方呢? 在使用null的过程中,经常会遇到一些让我们摸不着头脑的问题。下面这些问题,你都遇到过吗?

把null用在表字段的定义中

在定义表结构时,会经常遇到类似下面的字段定义:

`name` varchar(45) not null default '' comment '名称'

上面的语句表示:定义一个名称为name的字段,字段的默认值为‘’。当向表中新增数据的时候,该字段值不能为null,如果该字段的值没有明确指定的话,那么保存的值,默认为空字符串。

为什么不建议把字段的默认值设置为null呢?

其实null表示的是一种特殊含义,表示 “未知” 的意思,是一个 不确定的值 ,它不像空字符串,虽然空字符串表示字段值为空,但是它的含义是明确的,是确定的。

为了方便描述,建立如下的表结构:

CREATE TABLE `t` (
  `id` int(11) NOT NULL not null auto_increment,
  `a` int(11) ,
  `b` int(11)  not null DEFAULT 0,
  PRIMARY KEY (`id`) 
) ENGINE=InnoDB;

定义一个名称为t的表,表中有三个字段,主键idint类型的字段a,没有指定任何默认值。int 类型字段b,默认值为0

在表t中,字段a的定义,没有指定默认值,那么该字段的默认值就是null

可以通过插入一条数据进行验证:

insert into t (id),value(1);

然后通过查询语句进行查看:

select * from t;

你知道SQL的中NULL,该怎么处理吗?
可以看到,字段a的值为null,字段b的值为0.

从返回结果中,我们可以看到a的值,的确为null,那么我们在业务中如何判断这个值是否为null呢?换句话说,应该在where后面使用什么条件,来判断字段值为null呢?

在讨论null的判定方式前,需要先明确where后的条件表达式,可能返回的值。我们知道,where后的条件是一个boolean表达式,通常返回的结果有两种:truefalse。如果条件表达式返回为true,那么就把满足条件的数据集返回,否则不返回任何数据。

如果在判断条件中出现了null关键字后,条件表达式返回值,可能还会有第三种,也就是"未知",那where接受到"未知"的返回结果后,会怎么处理呢?

where对"未知"的处理和false的处理时一样的,也不会返回任何结果。

如何判断一个字段值是否为null

有时候,我们已经知道某个字段的值为null,但是我们如何进行判定呢?这里有两种方法:

select * from t where a= null;
select * from t where a is null;

第一条sql的返回结果:
你知道SQL的中NULL,该怎么处理吗?

第二条sql的返回结果:
你知道SQL的中NULL,该怎么处理吗?

根据返回的结果,可以发现第二种可以满足我们的需求。那么为什么第一种方式不可以,而第二种方式可以呢?

对于第一种方式,where a=null;表示的含义是:未知 等于 未知 吗?细品一下,好像不确定,因为不知道"未知"代表什么值,所以不好判定。那么对于这种不确定的结果,返回值也是"未知"。而where对"未知"的处理和false相同,不返回任何结果。

而对于第二种方式,where a is null;表示的含义是:a字段的值是未知的吗?这个比较好回答,a的值是null,的确是未知的。所以此时 where的返回值是true。将满足条件的数据返回。

所以,在判断一个字段的值是否是未知的,应该使用 is null,不能使用 = null;

null和not

结合where对条件的处理,我们发现条件的返回结果为falsenull时,数据库引擎对其处理都是一样的。那是不是就没有必要对falsenull进行区分了呢?

其实是有必要的,虽然where对两种处理结果的处理方式是一样的。但是呈现出的语义却是完全不同的,当where收到返回值null时,此时数据库引擎不知道该怎么处理,所以就返回了一个空的数据集,而收到false时,表示条件不满足,需要返回一个空的数据集。

除此之外,对于返回值为null的条件,我们在其前面添加 not,和在返回值为false的条件前添加not,条件的返回值是不同的。

举例如下:

select * from t where b = 1;
select * from t where b = null;

第一条sql的执行结果:
你知道SQL的中NULL,该怎么处理吗?

第二条sql的执行结果:
你知道SQL的中NULL,该怎么处理吗?

上面两个语句中,b=1 返回值为false,因为b的值为0b=null 返回值为 null,因为b=0null表示未知,null有可能是0,也可能不是0b=null的返回值还是 null。所以上面两条sql的返回结果都是空数据集。

如果给上面两个sql的判断条件前加上not后,返回结果会有影响吗?

我们继续验证下:

select * from t where not (b = 1);
select * from t where not (b = null);

第一条sql的执行结果:
你知道SQL的中NULL,该怎么处理吗?

第二条sql的执行结果:
你知道SQL的中NULL,该怎么处理吗?

根据返回的结果可以看到,第一条sql返回了一条数据,说明 not (b=1) 返回true,因为 b=1false

而第二条sql的返回结果依旧空数据集。因为 b=nullnull,是未知not (null)的结果仍然是未知

null与in

在使用 in的时候,遇到了null会产生什么结果呢?对于下面这些sql,他们的执行结果是怎样的呢?

(1) select * from t a in (0,1,null);

你知道SQL的中NULL,该怎么处理吗?

返回结果为空数据集,因为 anull,数据库引擎无法判断,一个值未知的值,是否存在于(0,1,null),所以数据库引擎对其的处理和false一样。

(2) select * from t b in (0,1,null);

你知道SQL的中NULL,该怎么处理吗?

返回结果不为空,因为 b的值是0,可以明确的确定,b的确存在于(0,1,null)中。

(3) select * from t where b in (1,2,null);

你知道SQL的中NULL,该怎么处理吗?

返回结果为空,因为null的值未知,有可能为0,也有可能不是0,所以数据库引擎,无法判断是否存在,所以条件的返回值是nullsql的返回结果为空。

总结

其实,明确了null表示未知的含义,那么在遇到null的场景,都可以把null表示的未知语义代入进去,再结合where对未知的处理机制,以前很多不确定的问题都可以迎刃而解了。