MySQL表字段推荐设置NOT NULL的理由

推荐用法

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,就容易忽略这个问题从而导致错误发生。


觉得内容还不错?打赏个钢镚鼓励鼓励!!👍