is not null 仅判断是否为 sql 的 null(缺失值),不识别空字符串、0等有效值;因 null 表示未知,而''、0是确定值,故需额外条件如 and col != '' 才能筛出真正有意义的非空数据。

IS NOT NULL 为什么不能判断空字符串或0?
IS NOT NULL 只检测数据库层面的“缺失值”,即 SQL 标准定义的 NULL——它不代表任何值,也不是空字符串、不是数字 0、不是布尔 FALSE。常见误解是以为 IS NOT NULL 能过滤掉空字符串 '' 或默认值,实际完全不会。
比如字段 name 存了 ''(空字符串)、age 存了 0,它们都满足 IS NOT NULL,会被查出来。真正要筛“有意义的非空”,得额外加条件:
WHERE name IS NOT NULL AND name != ''-
WHERE age IS NOT NULL AND age > 0(若业务中0无意义) - PostgreSQL 中还可配合
NULLIF(name, '') IS NOT NULL简化逻辑
在 WHERE 和 JOIN 中使用 IS NOT NULL 的差异
WHERE column IS NOT NULL 是常规过滤,而 JOIN ... ON t1.col = t2.col AND t2.col IS NOT NULL 这类写法容易出错:如果 t2.col 是 NULL,整个 ON 条件为 UNKNOWN,该行直接被排除——但这是隐式行为,不等于显式过滤。
更安全的做法是把非空约束放在 WHERE 子句,尤其涉及外连接时:
- LEFT JOIN 后想保留左表所有行,但只关联右表非空记录 →
LEFT JOIN t2 ON t1.id = t2.t1_id WHERE t2.col IS NOT NULL - 若把
t2.col IS NOT NULL放进ON,可能意外变成内连接效果
IS NOT NULL 在索引和性能上的实际影响
大多数数据库(MySQL、PostgreSQL、SQL Server)能用普通 B-Tree 索引加速 IS NOT NULL 查询,但前提是该列有索引且统计信息较新。
不过要注意几个现实限制:
- MySQL 5.7+ 对
IS NOT NULL走索引的前提是:该列没有允许NULL的历史遗留定义(比如建表时用了NOT NULL,那IS NOT NULL就恒真,优化器可能干脆不走索引) - Oracle 需要函数索引才能高效支持
IS NOT NULL(如CREATE INDEX idx ON t (col) WHERE col IS NOT NULL) - 如果查询同时含
IS NOT NULL和范围条件(如AND created_at > '2024-01-01'),复合索引顺序很重要:把IS NOT NULL列放前面通常没收益,优先放高选择性列
替代方案:COALESCE 和 NULLIF 怎么配合用?
当需要把 NULL 和空字符串统一视作“无效”,COALESCE 和 NULLIF 比堆砌 OR 更清晰:
比如筛选真实有内容的描述字段:WHERE COALESCE(NULLIF(description, ''), 'X') != 'X'
这等价于 “description 不是 NULL 且不等于空字符串”。相比 description IS NOT NULL AND description != '',它在嵌套表达式或视图中更易复用。但注意:NULLIF(a, b) 返回 NULL 当 a = b,否则返回 a;COALESCE 则取第一个非 NULL 值。
这种写法在 PostgreSQL 和 SQL Server 中表现稳定,MySQL 8.0+ 也支持,但旧版 MySQL 可能因类型隐式转换导致意外结果。










