SQL 中的 NULL
NULL 本身的含义
NULL本身在数据库中的含义为“unknown”:
- 代表未知;
- 不等于空字符串;
- 不等于 0;
NULL 的运算
逻辑运算
在 SQL 中判断是否为 NULL 不能用简单的 = NULL
,如:
1 | SELECT * FROM `users` WHERE `password` = NULL; |
这样子的语句相当于
1 | SELECT * FROM `users` WHERE false; |
原因是:
= NULL
本身的结果是 unknown;- 在逻辑表达式的其它部分已经执行完毕后,若“unknown”仍然存在,则将其按照
false
处理。
逻辑运算:
- (true and unknown) = unknown,
- (false and unknown) = false,
- (unknown and unknown) = unknown,
- (unknown or true) = true,
- (unknown or false) = unknown,
- (unknown or unknown) = unknown
举例:
1 | SELECT * FROM `users` WHERE true or `password` = NULL; |
正确的判断是否为 NULL 的方式应改为:
is NULL
is not NULL
可能会产生 unknown 的情况
-
属性没有默认值且设置可以为空,在该记录的该属性没有插入值时,默认为 NULL;
-
左连接、右连接中存在元组没有在另一个表中找到满足
on
指定条件的元组; -
算数运算中包含 NULL;
1
2
31 + NULL
1 * NULL
... -
逻辑运算中包含 NULL;
凡是逻辑运算中包含 NULL 的结果都为 unknown,没错,
NULL = NULL
结果同样为 unknown1
2
3= NULL
> NULL
!= NULL
NULL 可能引发的问题及解决方法
标量子查询问题
问题场景:如果我们想将所有用户的硬币数设置为所有用户的硬币总数:
1 | UPDATE `users` SET `coins` = ( |
此时,若存在用户的 coins
为 NULL 的话,那子查询得到的结果就变成了 NULL,原语句在这种情况下等价于:
1 | UPDATE `users` SET `coins` = NULL; |
这显然不是我们想要的结果。
解决方法有:
-
设置默认值。由于之前一直没理解 NULL 的含义,所以一直没有为属性设置默认值的习惯。其实设置默认值往往是解决 NULL 问题的高效且简单的解决方法。
-
筛除 NULL 的情况
1
2
3UPDATE `users` SET `coins` = (
SELECT SUM(`coins`) FROM `users` WHERE `coins` is not NULL;
);