结论:用IS NULL判断空值,用IFNULL()替换空值;二者不可混用,= NULL无效,COALESCE仅在多参数兜底时适用;IS NULL能走索引,函数包装如IFNULL(col,0) IS NULL则失效。

直接说结论:用 IS NULL 判断空值,用 IFNULL() 替换空值——这两者不能混用,也不能替换成 = NULL 或 COALESCE()(除非你真需要多参数兜底)。
WHERE 条件里怎么查出 NULL 值
常见错误是写 WHERE col = NULL 或 WHERE col != NULL,结果永远查不到数据,因为 NULL = NULL 返回的是 NULL(逻辑上“未知”),不是 TRUE。
- 正确写法只有两种:
WHERE col IS NULL或WHERE col IS NOT NULL -
IS NULL是操作符,不是函数,不加括号;ISNULL(col)是 MySQL 函数,等价但可读性差,不推荐 - 如果字段上有索引,
col IS NULL在大多数情况下能走索引(B-tree 索引支持IS NULL查询),但函数包装如IFNULL(col, 0) IS NULL会失效
SELECT 里怎么把 NULL 显示成默认值
想让查询结果里不出现 NULL,而是显示 0、'未知' 或当前时间,优先用 IFNULL() —— 它专为 MySQL 设计,语义清晰、性能好、参数少。
-
SELECT IFNULL(price, 0) AS price FROM products;→price为NULL时返回0 -
IFNULL()只接受两个参数,第二个是 fallback 值;COALESCE()支持多个参数,但 MySQL 中多数场景没必要,反而增加理解成本 - 注意:如果 fallback 值类型和原字段不一致(比如
IFNULL(created_at, 'N/A')),MySQL 会隐式转换,可能触发全表扫描或精度丢失
JOIN 后 WHERE 过滤 NULL 导致数据意外丢失
LEFT JOIN 后,右表字段在无匹配时自动为 NULL。此时若在 WHERE 里加条件过滤右表字段,会把整行干掉——这是最隐蔽也最常踩的坑。
- 错误写法:
LEFT JOIN orders o ON u.id = o.user_id WHERE o.status = 'paid'→ 没订单的用户全被过滤 - 正确做法之一:把条件挪到
ON子句:LEFT JOIN orders o ON u.id = o.user_id AND o.status = 'paid' - 另一做法:显式允许 NULL:
WHERE o.status = 'paid' OR o.status IS NULL,但语义容易歧义,慎用 - 本质问题在于
WHERE是在 JOIN 之后执行,而ON是在 JOIN 过程中起作用
聚合计算时 NULL 自动被忽略,但 COUNT 行为特殊
像 SUM()、AVG()、MAX() 都会跳过 NULL,这通常符合预期;但 COUNT() 的两个常用形式行为完全不同,极易误用。
-
COUNT(*)统计所有行,包括NULL字段所在的行 -
COUNT(col)只统计col非NULL的行数,等于SUM(CASE WHEN col IS NOT NULL THEN 1 ELSE 0 END) - 如果想统计“有值”的数量,用
COUNT(col);如果想统计“总记录数”,必须用COUNT(*),不能靠COUNT(IFNULL(col, 1))曲线救国
真正难处理的不是语法本身,而是业务语义是否允许 NULL:建表时没设 NOT NULL,后期补 IFNULL 就像贴创可贴;一个字段既存 '' 又存 NULL,清洗逻辑就得双重判断——这种混乱比写错一条 IS NULL 更伤筋动骨。


















