必须用IS NULL,因NULL是缺失值标记而非值,= NULL恒返回UNKNOWN,WHERE只保留TRUE行;正确写法为WHERE column IS NULL,它跨数据库通用且语义明确。

IS NULL 不能用等号判断,必须用专门操作符
SQL 里 NULL 不是值,而是“缺失值”的标记,所以 column = NULL 永远返回 FALSE 或 UNKNOWN,查不到任何行。必须用 IS NULL 或 IS NOT NULL。
常见错误现象:SELECT * FROM users WHERE email = NULL 返回空结果,即使表里真有 email 为空的记录。
-
WHERE column IS NULL是唯一标准写法(注意中间是IS,不是=) - 某些方言(如 PostgreSQL)支持
IS DISTINCT FROM做安全比较,但IS NULL更通用、更可读 - 别在
IS NULL前加括号搞成(column) IS NULL——虽然多数引擎容忍,但没必要,还可能干扰索引下推
WHERE 和 JOIN 中 NULL 判断的行为差异
IS NULL 在 WHERE 子句中过滤行,在 JOIN 条件里却可能让关联失败——因为 ON a.id = b.user_id 遇到任一端为 NULL 就不匹配,哪怕你写了 b.user_id IS NULL 也救不回来。
- 想查“没关联上用户的数据”,得用
LEFT JOIN+WHERE b.user_id IS NULL,而不是把IS NULL放在ON里 -
ON b.user_id IS NULL会强制让右表所有行都参与左连接(相当于笛卡尔积),极容易误查 - 如果业务真需要按 NULL 关联(比如默认配置),建议用
COALESCE(b.user_id, -1)转成确定值再比
索引对 IS NULL 查询是否有效?
大多数主流数据库(PostgreSQL、MySQL 8.0+、SQL Server)支持在 B-Tree 索引中存储 NULL,所以 WHERE status IS NULL 可以走索引——但前提是索引包含该字段且未被优化器放弃。
- MySQL 5.7 及更早版本默认不索引
NULL,需显式声明INDEX (status)(无需额外配置) - PostgreSQL 要确保字段没被
WHERE中其他高选择性条件“挤掉”索引使用优先级 - 避免写成
WHERE status IS NULL OR status = 'draft':OR 容易让优化器弃用索引,改用UNION ALL拆开更稳
字符串字段的 '' 和 NULL 要分开判断
空字符串 '' 和 NULL 在 SQL 中完全不等价。IS NULL 对 '' 返回 FALSE,反过来 = '' 对 NULL 也永远不成立。
- 常见场景:用户注册时没填邮箱,后端可能存
NULL或'',查询时得明确业务含义 - 保险写法:
WHERE email IS NULL OR email = '',或统一清洗数据,只留一种“空”表示 - PostgreSQL 可用
NULLIF(email, '') IS NULL把空字符串转成 NULL 再判,但别滥用,影响可读性
实际写的时候,先确认字段到底存的是 NULL 还是 '',再决定用 IS NULL 还是 = ''——这个区分点,线上出过太多漏查和误删。

















