WHERE子句中column = NULL查不到数据,因为NULL是缺失值标记而非值,=比较返回UNKNOWN而非TRUE,WHERE只保留TRUE结果;正确写法是WHERE column IS NULL。

WHERE子句里写 column = NULL 为什么查不到数据?
因为 SQL 中 NULL 不是值,而是“缺失值”的标记,它不等于任何东西——包括它自己。所以用 =、!= 或 判断 NULL 全部返回 UNKNOWN,而 WHERE 只认 TRUE,直接过滤掉。
- 错误写法:
WHERE name = NULL(永远不匹配) - 正确写法:
WHERE name IS NULL - 同理,
WHERE name != NULL或WHERE name NULL也无效,必须用IS NOT NULL - 注意:部分数据库(如 PostgreSQL)支持
IS DISTINCT FROM,能安全比较含NULL的表达式,但标准写法仍是IS NULL/IS NOT NULL
字符串字段为空字符串 '' 和 NULL 是两回事
空字符串是明确的、长度为 0 的字符串值;NULL 表示该字段根本没有值。很多业务逻辑会把这两者混为一谈,但 SQL 默认不自动等价处理。
- 要同时查出
NULL和空字符串:WHERE name IS NULL OR name = '' - 想统一视为空(比如清洗数据时):
WHERE COALESCE(name, '') = ''(COALESCE返回第一个非NULL值) - MySQL 有个陷阱:
''在某些排序或索引场景下可能被当作NULL处理(尤其在utf8mb4+COLLATE utf8mb4_0900_as_cs下),但判断逻辑不变——仍需显式写= ''或IS NULL
IS NULL 能用上索引吗?
可以,但取决于索引类型和数据库实现。B-tree 索引默认不存储全 NULL 键(PostgreSQL 除外,默认存;MySQL InnoDB 则只在联合索引中存 NULL,单列索引不存)。
- 单列索引上
WHERE status IS NULL在 MySQL 中通常走不了索引(除非是覆盖索引或启用了innodb_use_null相关优化) - 联合索引如
(user_id, status),WHERE user_id = 123 AND status IS NULL很可能走索引 - 更可靠的方式:给常查
NULL的字段建函数索引(如 PostgreSQL 的CREATE INDEX ON t ((status IS NULL)))或加一个计算列(如 MySQL 5.7+ 的虚拟列) - 别依赖
EXPLAIN里显示key就一定高效——要看rows和实际执行时间
聚合函数里 NULL 怎么算?
几乎所有聚合函数(COUNT、SUM、AVG、MAX、MIN)默认忽略 NULL,但 COUNT(*) 是例外:它统计所有行,不管字段是否为 NULL。
-
COUNT(col):只统计col IS NOT NULL的行 -
COUNT(*):统计整行,哪怕所有字段都是NULL也算 1 -
SUM(col)返回NULL当且仅当所有col都是NULL;只要有一个非NULL值,就正常求和 - 想把
NULL当 0 加进去?用SUM(COALESCE(col, 0))
真正容易漏的是:前端传参时把空字符串当 NULL 插入,或者 ORM 自动生成的 WHERE 条件没区分 is null 和 == ''。查不到数据时,先 SELECT <em> FROM t WHERE col IS NULL LIMIT 5</em> 和 SELECT FROM t WHERE col = '' LIMIT 5 分开看一眼,比翻文档快。










