is not null仅排除null值,不过滤空字符串'';需组合where col is not null and col != ''才能排除所有“空白”数据,因null表示未知,''是合法零长字符串。

IS NOT NULL 不能和空字符串混为一谈
很多人写 WHERE column_name IS NOT NULL 后发现还是查出了“空白”数据,其实是把 NULL 和空字符串 '' 当成一回事了。数据库里它们是完全不同的值:NULL 表示“未知/不存在”,而 '' 是一个长度为 0 的合法字符串。
如果你要排除所有“看起来为空”的数据,得同时处理两种情况:
WHERE column_name IS NOT NULL AND column_name != ''- 在 MySQL 中可简写为
WHERE column_name >> ''(利用隐式类型转换,但不推荐——可读性差且行为依赖 SQL 模式) - PostgreSQL 需显式写
TRIM(column_name) '',因为前后空格也会影响判断
WHERE col IS NOT NULL 在索引下不一定走索引
看似简单的过滤条件,执行计划里可能没走索引,尤其当字段有大量 NULL 值时。原因在于:部分数据库(如早期 MySQL MyISAM)对 NULL 值不建索引条目;即使 InnoDB 支持,优化器也可能因统计信息不准而放弃使用索引。
验证方式很简单:
- 用
EXPLAIN SELECT * FROM table WHERE col IS NOT NULL看key字段是否非NULL - 如果没走索引,且该字段查询频繁,考虑加函数索引(MySQL 8.0+):
CREATE INDEX idx_col_notnull ON table ((col IS NOT NULL)) - 更通用的做法是建普通索引 + 业务层保证该字段非空(比如设
NOT NULL约束)
NULL 安全比较:!= NULL 永远返回 false
新手常犯的错是写 WHERE column_name != NULL,结果一条数据都查不到。因为任何与 NULL 的常规比较(=、!=、、<code>IN 等)都返回 UNKNOWN,而 WHERE 只接受 TRUE 的行。
正确姿势只有两个:
-
IS NOT NULL(推荐,语义清晰) -
IS NULL的否定形式不行,别写NOT (column_name IS NULL)—— 多一层括号没坏处,但没必要 - 某些场景想用表达式判空,可用
COALESCE(column_name, '') != '',但注意COALESCE会阻止索引使用
不同数据库对 IS NOT NULL 的细微差异
标准 SQL 是统一的,但实际执行时要注意方言细节:
- SQLite 默认允许所有列存
NULL,哪怕你没声明,IS NOT NULL行为和其他库一致 - SQL Server 的
ANSI_NULLS OFF模式下,WHERE col != NULL会返回NULL行——但这是过时模式,新项目务必保持ON - Oracle 没有空字符串概念,
''就等价于NULL,所以WHERE col IS NOT NULL自动也过滤了空字符串
跨库迁移时最容易栽在这里:同一句 IS NOT NULL 条件,在 Oracle 里可能比 PostgreSQL 少查出几行,就因为后者把 '' 当有效值存着。











