必须用 IS NULL,= NULL 永远不生效;因为 NULL 是缺失标记而非值,所有 =、!= 等比较均返回 UNKNOWN,WHERE 只保留 TRUE 行,故 = NULL 查询必为空,而 IS NULL 是跨数据库通用的标准语法。

必须用 IS NULL,= NULL 永远不生效
SQL 中 NULL 不是值,而是“缺失”或“未知”的标记。所有涉及 =、!=、 的比较都会返回 UNKNOWN,而 WHERE 只保留 TRUE 行,所以 WHERE column = NULL 一定查不到任何数据——哪怕该列全是 NULL。
常见错误现象:
- 写
WHERE email = NULL→ 结果为空,但实际有大量未填邮箱的记录 - 写
WHERE status != 'done'→ 漏掉所有status IS NULL的行,因为NULL != 'done'是UNKNOWN
正确写法只有一种:WHERE column_name IS NULL。这个语法在 MySQL、PostgreSQL、SQL Server、Oracle 全部通用,且语义明确。
IS NULL 和 IS NOT NULL 的实际边界在哪
IS NOT NULL 只排除 NULL,不代表字段“有有效内容”。它会放过空字符串 ''、全空格 ' '、数字 0、默认日期 '0001-01-01' 等——这些都不是 NULL,但业务上常被当作“空”处理。
实操建议:
- 仅需过滤未赋值:用
WHERE phone IS NOT NULL - 要同时排除
NULL和空字符串:加AND phone != '' - 再剔除空白字符(MySQL/PostgreSQL):
AND TRIM(phone) != '' - SQL Server 需写成:
AND RTRIM(LTRIM(phone)) != ''
别指望 IS NOT NULL 自动帮你清理业务意义上的“空”,它只管数据库层面的 NULL 标记。
索引和性能上容易被忽略的细节
IS NULL 条件本身可以走索引,但效果取决于数据分布和索引结构:
- 如果某字段
NULL占比极高(比如 >95%),优化器大概率放弃索引,直接全表扫描 - 复合索引如
(a, b),WHERE a IS NULL AND b = 1通常无法利用该索引 - 高频查
NULL的场景,可考虑函数索引(PostgreSQL 支持CREATE INDEX ON t ((col IS NULL)))或加冗余布尔字段
真正影响性能的从来不是语法对错,而是你没意识到:这个查询是否真的需要扫一遍所有 NULL 值?有没有更前置的数据清洗或标记机制?
JOIN、GROUP BY、ORDER BY 中 NULL 的行为差异
NULL 在不同上下文表现不一致,容易引发隐性 bug:
-
JOIN ON a.id = b.id:任一侧为NULL就不匹配,NULL = NULL返回FALSE,不是TRUE - 想让
NULL匹配NULL,得显式写:ON (a.id = b.id) OR (a.id IS NULL AND b.id IS NULL) -
GROUP BY col:所有NULL会被归为同一组(这是标准行为) -
ORDER BY col:NULL默认排最前(PostgreSQL)或最后(MySQL),可用ORDER BY col IS NULL, col统一控制
最麻烦的不是不会写 IS NULL,而是忘了它在连接、分组、排序里根本不是“一个值”,而是一类特殊状态——你得按场景分别应对。

















