sql中null与空字符串''本质不同:null参与任何比较均返回unknown而被where排除,''则是确定的空值;需用is not null和!= ''联合判断才可真正过滤非空数据。

WHERE 字段 IS NOT NULL 和 != '' 是两回事
很多人写 WHERE name != '' 就以为过滤掉了空值,结果发现 NULL 还在结果里。因为 SQL 中 NULL 和空字符串 '' 完全不同:前者是“未知值”,后者是“已知的空内容”。NULL 参与任何比较(包括 !=、=、)都返回 UNKNOWN,而 WHERE 只接受 TRUE 的行,所以 NULL 自动被排除——但不是因为你写了条件,而是因为条件没成立。
-
WHERE col IS NOT NULL只过滤NULL,保留'' -
WHERE col != ''或WHERE col ''只过滤空字符串,保留NULL - 真正要“非空”(既不是
NULL也不是''),得两个条件一起写:WHERE col IS NOT NULL AND col != ''
CHAR/VARCHAR 默认填充空格带来的陷阱
MySQL 在 CHAR 类型字段中会用空格补齐长度,查询时如果用 = '' 或 TRIM(col) = '',可能误判。比如 CHAR(10) 存了 'a',实际存的是 'a '(9个空格)。这时候 col = '' 是 false,但 TRIM(col) = '' 也是 false;可一旦你写 LENGTH(col) = 0,结果还是 false——因为长度是 10。
- 优先用
VARCHAR替代CHAR,避免隐式空格填充 - 必须用
CHAR时,过滤空值建议统一用TRIM(col) != '',而不是col != '' - PostgreSQL 没这个行为,SQL Server 有类似问题但默认不填充,注意数据库差异
LIKE '%xxx%' 查询下空字符串和 NULL 都不会命中
如果你在模糊搜索场景下顺手加了个 WHERE name LIKE '%abc%',别以为它能帮你“顺便”过滤掉空值。实际上,NULL 和 '' 都不会匹配任何 LIKE 表达式——NULL LIKE '%abc%' 返回 UNKNOWN,'' LIKE '%abc%' 返回 FALSE。所以这句 WHERE 本身已经把这两类都剔除了,但属于“副作用”,不可依赖。
- 不要靠
LIKE当空值过滤手段,语义不清且易被后续修改破坏 - 如果业务上“空字符串”和 “NULL” 都算无效数据,显式写清楚:
WHERE name IS NOT NULL AND TRIM(name) != '' AND name LIKE '%abc%' - 注意
TRIM()在 MySQL 5.7+ 支持,旧版本要用TRIM(BOTH ' ' FROM name)
ORM(如 Django/SQLAlchemy)里容易漏掉 NULL 判断
用 ORM 写查询时,.filter(name__ne='') 这类写法通常只生成 != '',不会自动加上 IS NOT NULL。尤其当字段允许 NULL,又没设 default,表里就真可能出现大量 NULL,导致前端看到“空白项”却查不到原因。
- Django:用
.exclude(name='')+.exclude(name__isnull=True),或合起来.exclude(Q(name='') | Q(name__isnull=True)) - SQLAlchemy:用
and_(Table.name != '', Table.name.isnot(None)),注意不是is not None,而是isnot(None) - 检查迁移文件里字段是否加了
nullable=False,从源头减少 NULL 可能性
空字符串和 NULL 的区分不是语法细节,是数据建模的基本假设。一旦混用,WHERE 条件就变成概率性生效——这次对,下次错,还很难复现。










