sql中不能用!=或直接查询null值,因为null与任何值比较结果均为unknown,而where只保留true行;正确写法需显式判断:where col != 'val' or col is null。

SQL中不能用 != 或 查询 NULL 值
直接写 WHERE column != 'value' 或 WHERE column 'value' 看似合理,但遇到 NULL 时会漏掉所有该列为 NULL 的记录。因为 SQL 中任何与 NULL 的比较(包括 !=、=、)结果都是 UNKNOWN,而 WHERE 只保留结果为 TRUE 的行。
常见错误现象:明明表里有 NULL 数据,但查询结果里完全看不到,还以为数据丢了。
- 正确做法是显式加上
OR column IS NULL,例如:WHERE column != 'abc' OR column IS NULL - 如果想排除
NULL,也必须单独写AND column IS NOT NULL,不能依赖!=自动过滤 - 某些方言(如 PostgreSQL)支持
IS DISTINCT FROM,可安全比较含NULL的值:WHERE column IS DISTINCT FROM 'abc'
!= 和 在所有主流数据库中都可用,但语义完全等价
MySQL、PostgreSQL、SQL Server、SQLite 都同时支持 != 和 ,二者行为一模一样,没有任何性能或兼容性差异。选哪个纯属团队风格或个人习惯。
使用场景:当确定列不含 NULL,或已通过 IS NOT NULL 显式约束时,两者任选其一即可。
- Oracle 早期只认
,但现在也支持!= - 避免混用:同一项目里统一用
!=或统一用,减少代码审查干扰 - 注意不要写成
!==(JavaScript 风格),SQL 不识别,会报错:ERROR: syntax error at or near "!"
字符串比较要注意大小写和尾部空格
!= 和 执行的是数据库默认的 collation 比较,不是简单字节对比。这意味着:
- 在默认大小写不敏感排序规则(如
utf8mb4_0900_as_cs以外的多数 MySQL 默认规则)下,'ABC' != 'abc'返回FALSE,整行被过滤掉 - SQL 标准规定字符串比较会忽略末尾空格,所以
'hello' = 'hello '为TRUE,那么'hello' != 'hello '就是FALSE - 若需精确字节比较,MySQL 可用
BINARY:WHERE BINARY column != 'Value';PostgreSQL 可用::bytea或encode(column::bytea, 'escape')
性能上,!= / 通常无法走索引范围扫描
虽然大多数数据库对 != 能用索引(比如通过 index scan + 过滤),但它无法像 >、 那样利用 B-tree 的有序结构做高效范围跳转。实际执行计划里常看到 <code>Index Scan 而非 Index Range Scan。
容易被忽略的地方:当表很大、且该字段选择性又低(比如只有 3–4 个不同值),!= 'X' 可能导致数据库放弃索引,直接走顺序扫描(Seq Scan)。
- 优化建议:若业务逻辑允许,改写成正向条件更可靠,例如把
status != 'done'拆成status IN ('pending', 'error', 'running') - 检查执行计划:务必用
EXPLAIN(PostgreSQL/MySQL)或SET SHOWPLAN_ALL ON(SQL Server)确认是否真走了索引 - 复合索引中,!= 条件只能用到最左前缀部分,后续列无法用于索引查找










