因为NULL是缺失值标记而非值,= NULL在SQL三值逻辑中恒返回UNKNOWN,而WHERE只保留TRUE行,故查不到任何数据;正确写法是WHERE col IS NULL。

WHERE col = NULL 为什么查不到任何数据
因为 = 是值比较运算符,而 NULL 不是值,它是“缺失值”的标记。SQL 使用三值逻辑(True/False/Unknown),col = NULL 的结果永远是 UNKNOWN,而 WHERE 子句只保留计算结果为 TRUE 的行,UNKNOWN 被当作 FALSE 处理。
- 执行
SELECT * FROM users WHERE email = NULL返回空结果集,哪怕email列全是NULL - 同理,
WHERE age != NULL、WHERE name ''(当name为NULL时)也都不生效 - Oracle、PostgreSQL、SQL Server、MySQL 全部遵循这一规则,不是某家数据库的“bug”
IS NULL 是唯一标准写法
IS NULL 不是语法糖,它是 SQL 标准中专为判断缺失值设计的谓词,语义明确且跨库兼容。
- 正确写法:
WHERE shipped_at IS NULL、WHERE backup_name IS NOT NULL - 它不依赖字段类型,对
INT、VARCHAR、JSON等都有效 - 在有索引的列上,
IS NULL通常能走索引(如 PostgreSQL B-tree 默认包含NULL;MySQL InnoDB 对IS NULL也支持索引下推) - 别混淆:
IS NOT NULL≠!= ''或> 0——空字符串和数字零都不是NULL
两个 NULL 想要“相等”怎么办
普通 = 在两边都是 NULL 时仍返回 UNKNOWN,导致 JOIN 或 WHERE a = b 漏掉这些行。必须显式处理空值语义。
- 通用写法:
WHERE (a = b) OR (a IS NULL AND b IS NULL) - MySQL/MariaDB 简化方案:
WHERE a b(是 NULL 安全等于,NULL NULL返回TRUE) - PostgreSQL 可用:
WHERE a IS NOT DISTINCT FROM b - 注意:
不是标准 SQL,迁移到其他数据库时需重写
容易被忽略的 NULL 隐形陷阱
就算记住了 IS NULL,在聚合、连接、表达式里仍可能翻车。
-
COUNT(col)自动跳过NULL行,COUNT(*)统计所有行——两者完全不等价 -
WHERE col1 = col2在任一列为NULL时整行被过滤,不是“不匹配”,而是“无法判断” -
COALESCE(col, 'default')很好用,但要注意类型:比如COALESCE(int_col, 'N/A')在强类型库(如 PostgreSQL)会报错 - 建表时若写了
NOT NULL DEFAULT '',那这列根本存不了NULL,IS NULL永远查不到数据
实际写查询前,先确认字段是否真允许 NULL、有没有默认值、以及你真正想筛的是“缺失值”还是“空字符串”——这两个概念在 SQL 里天差地别。

















