点击蓝字关注我们
大家好,我是杰哥
相信Mysql大家经常在用吧,那你肯定也知道下面这两个存在的事实。相信很多人在最初跟我一样,也会觉得很神奇,想着mysql也真是任性,规则想怎样定就怎样定,不信你看看
一 现象
你知道为何吗?
01.判断是否为null值,只能使用is (not) null
先来创建一个"test_user"表,建表语句如下
CREATE TABLE `test_user` (`id` varchar(10) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '用户id',`name` varchar(32) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '姓名',`age` int(10) DEFAULT NULL COMMENT '年龄',`sex` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '性别',`t_id` int(11) DEFAULT NULL COMMENT '关联id',PRIMARY KEY (`id`),UNIQUE KEY `t_index` (`t_id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci ROW_FORMAT=DYNAMIC;
其中id为主键,t_id列为唯一索引列
接下来,向表中插入两条数据,其中一条数据的name列的值为null
INSERT INTO `test_user` VALUES ('1', '杰哥', 21, '1', 1);INSERT INTO `test_user` VALUES ('2', NULL, 22, '0', 3);
OK,准备工作已完毕。接下来,让我们分别测试一下is null 、=null 以及!=null的查询情况
1)select * from test_user where name is NULL;

查询结果即为:name值为null的记录
2)select * from test_user where name = NULL;

查询结果为0条记录
3)select * from test_user where name != NULL;

查询结果为0条记录
很明显,只有is null 这种条件,查询的结果才是我们真正想要的,而=null 和!=null的条件似乎与"where false"的效果是一致的,怎样都没有记录返回
再来看看下面这个现象
02.唯一索引不可以重复,但是会出现多个null值
我们看到,t_id字段是一个唯一索引,此时向表里插入一条t_id为1的记录

会出现索引冲突的问题
再来添加两条t_id为null的数据
INSERT INTO `adp_test`.`test_user`(`id`, `name`, `age`, `sex`, `t_id`) VALUES ('3', '小明', 20, '1', NULL);INSERT INTO `adp_test`.`test_user`(`id`, `name`, `age`, `sex`, `t_id`) VALUES ('4', '小花', 20, '0', NULL);

我们发现两条都可以成功
也就是说唯一索引虽然不能重复,但是却允许多个null值
二 本质
究竟是为何?
也许你以前从来没有注意到这一点,但现在看到这个现象之后,一定能得出:
之所以会出现这两个现象,是因为每个null其实都对应不一样的值。是的,也可以理解成:
每个null其实都是一块独一无二的空间,因此每个null都是不相同的
三 延伸
其他说法
此外,我们还会经常说到要尽量在表里面对于字段要尽可能地声明not null,或者最好不在不为索引列中放null
这又是为何呢?
1 null值的存储结构

记录头信息,它是由固定的
5个字节组成。
5个字节也就是
40个二进制位,不同的位代表不同的意思,比如说是否删除的标记位啊之类的信息,此处不是重点,就先不赘述了
若能确定该字段不可能为null的时候,肯定要加上not null约束
若字段有可能为null的话,也要尽量加上not null。用默认值(如空字符串、0等值)去替代null值,这样不仅符合真实业务逻辑,也可以尽可能地节省空间,从而提升查询效率
2 索引中存在null时如何处理

explain SELECT * from test_user where t_id is null;

我们看到,该语句使用到了索引。
但当我们再更新id为2的行的t_id的值为null,出现了神奇的一幕

innodb_stats_method它包含三个值:
nulls_equal:表示null值都相同
nulls_unequal:表示null值都不同
nulls_ignored:忽略掉null值

当当当,豁然开朗,有木有~
3 null值与空字符串的比较
很多文章常常将null值与空字符串进行比较,其实在我看来,根本没有比较的意义。因为,在mysql的设计中,空值''与null值本身就是不一样的,可以说空值,是另一个特殊的存在。它不占空间,就是一个非null的值,那么自然跟null是不一样的。所以再要出现设置了not null约束的列,依旧可以插入空字符串值,就没什么想不通的了
四 总结
总而言之

往期精彩回顾

SpringCloud篇章





