MySQL中记得用not null,不然就滚蛋!
上午我收到一条短信,内容是“尊敬的 null 你好,XXX”,当时我就笑了。
图片来自 Pexels
我仿佛看到了那个程序员小姐姐被喷的场景,那是个温暖的午后,明媚的阳光洒在办公桌旁,小姐姐正撸着自己的代码,突然… …
“啪啪啪!!别睡了哈哥,老板叫你过去开会!”
言归正传,出现这种情况的原因一般是数据库的数据问题造成的,我大胆猜测几种场景,同学们可以在评论区补充:
①首次名称入库时出错,把我的名称填写失败,MySQL 默认成 null 值,查询时格式化成了’null’字符串。
②我注册时故意在名称中加了 \n、\r 等下流的数据,导致查询时返回了空字符串’’,正则校验时又出现空指针。
③我把 id 设置为’null’(别,兄弟们,我还能这么无聊了?~~)
字段尽可能用 NOT NULL,而不是 NULL,除非有特殊情况!
但却都只给结论也不说明原因,就像喝鸡汤不给勺子一样,有点膈应,让不少同学对这些结论只知其一,不明其二。坦白说,老司机也不一定清楚为啥,可能就是他领导让他这么干而已~~
就像我领导,记得我刚来公司时,他语重心长的叮嘱我:MySQL 建表字段记得用 not null,不然就滚蛋!🙃🙃🙃
今天我就带你来弄清楚为啥建议你建表字段尽量都使用 not null!
NULL columns require additional space in the rowto record whether their values are NULL. For MyISAM tables, each NULL columntakes one bit extra, rounded up to the nearest byte.
NULL 列在行中需要额外的空间以记录其值是否为 NULL。对于 MyISAM 表,每个 NULL 列都多花一位,四舍五入到最接近的字节。
其实这是官方在委婉的告诉你,别用 NULL 就完了~~
下面我们来看看 NULL 值有多少坑,这里我会结合 NULL 字段,和你着重说明 sum 函数、count 函数,以及查询条件为 NULL 值时可能踩的坑。
mysql> select * from demo0527;
+----+------------+-------+------+
| id | name | money | age |
+----+------------+-------+------+
| 1 | 陈哈哈1 | 100 | NULL |
| 2 | 陈哈哈2 | NULL | NULL |
| 3 | NULL | 100 | NULL |
+----+------------+-------+------+
3 rows in set (0.00 sec)
————————————————
我们通过下面三个用例,结合数据库中表 demo0527 的 null 值来看看:
示例一:通过 sum 函数统计一个只有 NULL 值的列的总和,比如 SUM(age)。
示例二:select 记录数量,count 使用一个允许 NULL 的字段,比如 COUNT(name)。
示例三:使用 =NULL 条件查询字段值为 NULL 的记录,比如 money=null 条件。
SELECT SUM(age) from demo0527;
SELECT count(name) from demo0527;
SELECT * FROM demo0527 WHERE money=null;
mysql> SELECT SUM(age) from demo0527;
+----------+
| SUM(age) |
+----------+
| NULL |
+----------+
1 row in set (0.00 sec)
mysql> SELECT count(name) from demo0527;
+-------------+
| count(name) |
+-------------+
| 2 |
+-------------+
1 row in set (0.00 sec)
mysql> SELECT * FROM demo0527 WHERE money=null;
Empty set (0.00 sec)
得到的结果,分别是 NULL、2、空 List;显然,这三条 SQL 语句的执行结果和我们的期望不同:
虽然表中的 age 都是 NULL,但 SUM(age) 的结果应该是 0 才对。
虽然第三行记录的 name 是 NULL,但查记录总行数应该是 3 才对。
使用 money=NULL 并没有查询到 id=2 的记录,查询条件失效。
三个示例的原因分别是:
①MySQL 中 sum 函数没统计到任何记录时,会返回 null 而不是 0,可以使用 IFNULL(null,0) 函数把 null 转换为 0。
②在MySQL中使用count(字段),不会统计 null 值,COUNT(*) 才能统计所有行。
③MySQL 中使用诸如 =、<、> 这样的算数比较操作符比较 NULL 的结果总是 NULL,这种比较就显得没有任何意义,需要使用 IS NULL、IS NOT NULL 或 ISNULL() 函数来比较。
SELECT IFNULL(SUM(age),0) FROM demo0527;
SELECT COUNT(*) FROM demo0527;
SELECT * FROM demo0527 WHERE age IS NULL;
mysql> SELECT IFNULL(SUM(age),0) FROM demo0527;
+--------------------+
| IFNULL(SUM(age),0) |
+--------------------+
| 0 |
+--------------------+
1 row in set (0.00 sec)
mysql> SELECT COUNT(*) FROM demo0527;
+----------+
| COUNT(*) |
+----------+
| 3 |
+----------+
1 row in set (0.00 sec)
mysql> SELECT * FROM demo0527 WHERE age IS NULL;
+----+------------+-------+------+
| id | name | money | age |
+----+------------+-------+------+
| 1 | 陈哈哈1 | 100 | NULL |
| 2 | 陈哈哈2 | NULL | NULL |
| 3 | NULL | 100 | NULL |
+----+------------+-------+------+
3 rows in set (0.00 sec)
另外值得注意的是,不仅 money=NULL 条件查不到字段值为 NULL 的记录,当我们使用 SELECT * FROM demo0527 WHERE money <>100;来查询 id=2 这行时,也是查不到任何数据的。
mysql> SELECT * FROM demo0527 WHERE money <>100;
Empty set (0.02 sec)
可见 MySQL 库中的 NULL 值很容易导致我们在统计、查询表数据时出错。
这里有些同学可能会问有没有性能上的提升,算不算 SQL 优化,其实把 NULL 列改为 NOT NULL 带来的性能提升可以忽略,除非确定它带来了问题,否则不需要把它当成优先的优化措施。
编辑:陶家龙
精彩文章推荐: