必须用is null判断null,因null是未知标记而非值,=null恒返回unknown被where过滤;正确写法仅有is null和is not null,二者是跨数据库兼容的标准谓词。

WHERE 判断 NULL 值必须用 IS NULL,不能用 = NULL
SQL 中 NULL 表示“未知值”,不是数据,也不是空字符串或零。因此任何与 NULL 的等值比较(如 = NULL、!= NULL、 NULL)结果都是 UNKNOWN,在 WHERE 中会被当作 FALSE 过滤掉——也就是说,写 WHERE col = NULL 永远查不到任何行。
正确写法只有两个:IS NULL 和 IS NOT NULL。
-
SELECT * FROM users WHERE email IS NULL;—— 查邮箱为空的记录 -
SELECT * FROM orders WHERE shipped_at IS NOT NULL;—— 查已发货的订单 - 别写
WHERE status = NULL,它不报错但永远没结果
区分 NULL、空字符串和 0:三者完全不同
比如一个 varchar 字段,NULL 表示“该字段值未提供/未知”,''(空字符串)表示“明确提供了空内容”,而 0 是数值零。它们在 WHERE 中必须分开处理:
-
WHERE name IS NULL—— 名字字段根本没填 -
WHERE name = ''—— 名字填了但填的是空字符串 -
WHERE age = 0—— 年龄明确是 0(合法数值) - 如果想同时查“未填或填了空字符串”,得写:
WHERE name IS NULL OR name = ''
在组合条件中,NULL 判断优先级容易被忽略
当 AND 或 OR 与其他条件混用时,IS NULL 的逻辑容易被误读。例如:
WHERE status = 'active' AND created_at IS NULL —— 这条没问题,要求状态是 active 且创建时间为空
但下面这句就有陷阱:
WHERE status = 'active' OR created_at IS NULL —— 它会把所有 created_at 为空的记录都拉出来,不管 status 是什么
- 如果本意是“查 status 为空或为 active”,应写:
WHERE status IS NULL OR status = 'active' - 涉及多个
IS NULL时,建议加括号明确逻辑,比如:WHERE (a IS NULL OR b IS NULL) AND c = 1 - 某些数据库(如 PostgreSQL)支持
IS DISTINCT FROM来统一处理NULL比较,但 MySQL 和 SQL Server 不支持,别硬套
索引对 IS NULL 查询是否有效?看情况
普通 B-tree 索引默认不存储全 NULL 键(MySQL 5.6+、PostgreSQL 支持索引 NULL,但行为有差异),所以 WHERE col IS NULL 可能无法走索引,尤其当该列 NULL 值占比很高时,优化器可能直接选全表扫描。
- MySQL 中,如果建的是复合索引(如
INDEX(status, created_at)),WHERE status = 'draft' AND created_at IS NULL仍可能命中索引 - PostgreSQL 中,
CREATE INDEX idx ON t (col) WHERE col IS NULL;可建部分索引加速 NULL 查询 - 别假设
IS NULL一定慢,也别假设一定快——执行计划(EXPLAIN)才是唯一依据
实际写查询时,先确认业务语义里“空”到底指什么(缺失?未设置?还是有意留空?),再决定用 IS NULL、= '' 还是其他判断;一旦涉及性能敏感路径,EXPLAIN 看一眼比凭经验靠谱得多。










