推荐用法
NOT NULL结合DEFAULT空值使用,即not null default ‘’。
例:
`name` varchar(32) not null default '' comment '姓名',
`amount` decimal(10, 2) not null default '0' comment '余额',
`status` int(4) not null default '1' comment '状态:1有效 0无效',
具体的理由如下:
一、null会导致语义不清晰
null 和 not null default ‘’ 二者所表达的含义是不一样的。null表示这个值是未知的;’’空值表示这个值已知,就是个空值空文本。
二、null会导致等号表达式失效
对于null值的判断,不能直接使用=,而需要使用is关键字。
select null=null, null!=null, null is null, null is not null;
null=null|null!=null|null is null|null is not null|
---------+----------+------------+----------------+
| | 1| 0|
(这里的null有点像C语言中未初始化的局部变量,实际可能是个垃圾值,故而null!=null。这个理解不准确,没有实际验证过底层逻辑是否是这样的,暂时用来辅助理解吧。)
所以针对null值的判断,必须使用is或者is not 关键字。有的人可能会说,那就用,没啥问题啊?但是会增加我们在开发时的复杂度。举个例子:
当前我们有个表A,使用a、b两个字段做联合唯一索引,也就是说可以通过a+b唯一的找到一条记录,充当主键的作用。现有一个save方法,逻辑是:通过a+b的值判断数据是否已经存在,有则更新,无则新增。正常代码逻辑一般为:
old = dao.selectByAB(a,b);
if(old==null){
insert();
}else{
update();
}
其中selectByAB对应的sql为:
select * from A where a=#{a} and b=#{b}
如果说ab的值允许为null的话,我们就得额外增加代码使用is关键字处理,否则可能会得出错误的结果。(因为null=null结果是null查找不出正确的数据)
还有一个原因是,虽然null=null的结果还是null,但是我们在使用distinct、group by、order by时,null值又会被认为是相同值。
三、null会导致值运算失效
select null+1;
null+1|
------+
|
null进行运算之后,结果还是为null。
四、聚合函数会忽略null值
表中存在null的数据在进行count统计时,这些数据会被忽略,举个例子:
drop table if exists `user`;
create table `user`(
`id` bigint(20) not null auto_increment comment '主键id',
`name` varchar(32) comment '姓名',
primary key (`id`)
) engine=innodb auto_increment=1 default charset=utf8mb4 comment='user表';
insert into `user`(`name`) values ('高启强'),('安欣'),(null);
分别对id和name字段进行count查询
select count(*),count(`id`),count(`name`) from `user`;
count(*)|count(`id`)|count(`name`)|
--------+-----------+-------------+
3| 3| 2|
这显然是不符合我们的预期的。虽然在实际开发中一般都是使用count(*)
或者对主键id字段进行统计数量,但是避免不了有些场景是需要count其他字段的,在这种场景下,如果字段允许为null,就容易忽略这个问题从而导致错误发生。