MySQL里查数据时那些空值到底咋处理才不出错呢?
- 问答
- 2025-12-26 09:10:16
- 2
基于常见的MySQL使用经验、开发者社区讨论如Stack Overflow、以及官方文档中关于NULL值的说明)
空值,在MySQL里就是NULL,它是个特别让人头疼的东西,它不代表0,也不代表空字符串"",它就代表“啥也没有”、“未知”或者“不适用”,你把它当成一个黑洞或者一个问号就行,正因为这种“未知”的特性,很多我们习以为常的查询方式在它面前就失灵了,导致查不到想要的数据或者结果不对。
第一大坑:用等号(=)去判断是不是NULL,完全没用。
这是新手最容易掉进去的坑,比如你有一张用户表,有些用户的电话号码字段是NULL,你想找出没留电话的人,很可能会这么写:
SELECT * FROM users WHERE phone_number = NULL;
结果呢?一条记录都查不出来!为啥?因为NULL是“未知”,两个“未知”比较(phone_number是否等于另一个“未知”NULL),结果还是“未知”,在MySQL的逻辑里,“未知”就被当成假(FALSE),所以条件不成立。
正确的做法是使用 IS NULL 或 IS NOT NULL。

你得用专门的语法来对付它:
-- 找出电话号码为空的人 SELECT * FROM users WHERE phone_number IS NULL; -- 找出电话号码不为空的人 SELECT * FROM users WHERE phone_number IS NOT NULL;
这样才能得到正确的结果,对NULL进行任何普通的比较操作(=, <, >, <>),结果都是NULL,也就是假。
第二大坑:用逻辑运算符(AND, OR)时,NULL会搅局。
当你的查询条件里有AND和OR,并且涉及NULL值时,结果可能会出乎意料,逻辑运算遇到NULL时,会遵循“三值逻辑”(真、假、未知)。
- AND操作:真 AND NULL = NULL(未知);假 AND NULL = 假,意思是,只要有一个条件是假,结果肯定是假,但如果一个条件是真,另一个是NULL,结果就成了未知(假)。
- OR操作:真 OR NULL = 真;假 OR NULL = NULL(未知),意思是,只要有一个条件是真,结果就是真,但如果一个条件是假,另一个是NULL,结果就是未知(假)。
举个例子,你想找“年龄大于30岁或者电话号码为空”的用户:

SELECT * FROM users WHERE age > 30 OR phone_number IS NULL;
这个查询没问题,但如果你不小心写成了:
SELECT * FROM users WHERE age > 30 OR phone_number = NULL;
由于 phone_number = NULL 永远返回NULL(假),你的查询结果就只会包含年龄大于30的人,完全漏掉了电话号码为NULL的那些人。
第三大坑:对包含NULL的字段进行排序、分组和计算。
-
排序(ORDER BY):当你按一个可能为NULL的字段排序时,NULL值会被视为最小值,如果是升序(ASC),它们会排在最前面;降序(DESC)则排在最后面,这点需要心里有数,别看到一排NULL以为数据错了。
-
分组(GROUP BY):如果按一个包含NULL的字段分组,所有的NULL值会被归为同一组,这通常是符合预期的,但要知道有这个特性。

-
计算和函数(如COUNT, SUM, AVG):这是个大问题!
COUNT(字段名):这个函数会忽略NULL值,它只计算该字段非NULL的行数,如果你想知道总共有多少行,应该用COUNT(*),表里有10个用户,3个电话号码是NULL,COUNT(phone_number)只会返回7,而不是10。SUM(), AVG()等聚合函数:同样会忽略NULL,如果你有一列数字[10, 20, NULL, 30],SUM()的结果是60,AVG()的结果是20 (60/3),而不是60/4=15,如果你希望把NULL当0处理,需要用IFNULL()或COALESCE()函数先转换一下,AVG(IFNULL(column_name, 0))。
第四大坑:用IN和NOT IN时,列表里有NULL。
IN 列表里有NULL,问题不大,因为 值 IN (1, 2, NULL) 等价于 值=1 OR 值=2 OR 值=NULL,如果值匹配1或2,结果就是真;如果不匹配,最后那个 值=NULL 是未知,但整体结果可能还是真或假。
但 NOT IN 就危险了。值 NOT IN (1, 2, NULL) 等价于 值<>1 AND 值<>2 AND 值<>NULL,问题出在最后一部分 值<>NULL,这个比较永远返回NULL(未知),而真 AND 未知 = 未知,所以整个条件的结果就是未知(假),这意味着,只要NOT IN的列表里有一个NULL,整个查询结果可能一条都出不来!务必确保NOT IN后面的子查询或列表不包含NULL值。
怎么才能系统地避免这些坑?
- 设计表的时候就想清楚:这个字段真的允许为NULL吗?如果业务上一定有值,就果断地把字段设为
NOT NULL并设置默认值(比如空字符串或0),从源头上减少NULL,是最根本的解决办法。 - 查询时养成习惯:只要字段可能为NULL,条件判断就用
IS NULL或IS NOT NULL,对字段进行计算或聚合时,先想想NULL的影响,必要时用IFNULL()函数给它一个默认值。IFNULL(column_name, replacement_value)函数会在column_name为NULL时返回replacement_value,否则返回column_name本身,还有一个更强大的COALESCE(value1, value2, ...)函数,它会返回参数列表中第一个非NULL的值。 - 测试时故意加入NULL:在测试你的SQL查询时,别忘了在数据库里故意放几条包含NULL值的记录,看看你的查询是否还能返回预期结果,这是发现潜在问题的最好方法。
处理MySQL里的空值,核心就是记住它的“未知”属性,不要用常规思维去对待它,多用专门为它设计的语法和函数,并在设计和测试阶段就把它考虑进去,这样就能大大减少出错的概率。
本文由太叔访天于2025-12-26发表在笙亿网络策划,如有疑问,请联系我们。
本文链接:http://www.haoid.cn/wenda/68701.html
