where子句中必须用is not null而非!= null或 null,因null与任何值比较均返回unknown;null表示未知,''是空字符串,语义不同;is not null可走索引但需注意数据库差异及避免函数包裹。

WHERE子句中必须用 IS NOT NULL,不能用 != NULL 或 NULL
SQL标准规定 NULL 与任何值(包括它自己)比较都返回 UNKNOWN,不是 TRUE 或 FALSE。所以 WHERE column != NULL 永远不匹配任何行,哪怕该列确实全为 NULL。这是新手最常踩的坑。
正确写法只有:WHERE column IS NOT NULL。注意中间是 IS,不是 =,也不是 ==。
-
WHERE name != NULL→ 无效,查不到任何记录 -
WHERE name IS NOT NULL→ 正确,查出所有非空name -
WHERE name = 'abc' OR name IS NOT NULL→ 逻辑冗余,= 'abc'已隐含非空
字符串字段要区分 NULL 和空字符串 ''
数据库里 NULL 表示“未知/未定义”,而 '' 是一个明确存在的、长度为0的字符串。两者在语义和查询行为上完全不同。
如果业务上认为“空字符串”也属于“无效值”,需要显式排除:
WHERE description IS NOT NULL AND description != ''- PostgreSQL 可用
NULLIF(description, '') IS NOT NULL - MySQL 中
TRIM(description) != ''还得额外防空白字符,建议组合写:description IS NOT NULL AND TRIM(description) != ''
IS NOT NULL 在索引使用上的实际表现
大多数主流数据库(如 PostgreSQL、SQL Server、MySQL 8.0+ 的 InnoDB)对 IS NOT NULL 能有效利用 B-tree 索引,但前提是该字段本身有索引,且查询没有其他拖慢执行计划的因素。
不过要注意:
- Oracle 对
IS NOT NULL使用索引的前提是:索引列不能全为NULL(即索引必须包含至少一个非空值) - 如果字段允许
NULL且索引是单列,那么IS NOT NULL通常走索引范围扫描;但若加上ORDER BY或LIMIT,优化器可能改用全表扫描——建议配合EXPLAIN验证 - 避免在
IS NOT NULL条件上再套函数,比如WHERE UPPER(email) IS NOT NULL—— 这会让索引失效
聚合查询中 GROUP BY 和 IS NOT NULL 的交互容易被忽略
当对某字段分组并统计时,NULL 值会自动聚合成单独一组(除非被过滤掉)。如果你只想要非空值的分组结果,WHERE 必须放在 GROUP BY 之前,而不是靠 HAVING 补救。
错误示范:GROUP BY category HAVING category IS NOT NULL → HAVING 是对分组后结果过滤,但 category IS NOT NULL 在分组维度上恒成立或无意义,语法可能报错或行为不可控。
正确做法始终是:
SELECT category, COUNT(*) FROM products WHERE category IS NOT NULL GROUP BY category- 若需同时统计
NULL组,可用CASE WHEN category IS NULL THEN 'unknown' ELSE category END转换后再分组
真正麻烦的是嵌套查询或视图里漏掉这一层过滤——上线后才发现报表里多出一堆 “(null)” 分组,还得回溯改逻辑。











