NOT LIKE 会过滤 NULL 值,因其判断结果为 UNKNOWN,而 WHERE 只保留 TRUE 行;需显式添加 IS NULL 或 IS NOT NULL 条件处理空值。

NOT LIKE 会漏掉 NULL 值,这点必须提前处理
直接写 WHERE column_name NOT LIKE '%abc%' 看似正确,但只要该列存在 NULL 值,这些行就**不会出现在结果里**。因为 SQL 中 NULL NOT LIKE 'xxx' 的结果是 UNKNOWN,而 WHERE 只保留 TRUE 行。
实操建议:
- 显式补上
OR column_name IS NULL(如果业务允许返回 NULL) - 更常见的是加
AND column_name IS NOT NULL,确保只查有值的记录 - 千万别依赖
NOT LIKE自动覆盖 NULL 场景
用 CHARINDEX 或 LOCATE 替代 NOT LIKE 更精准
NOT LIKE 是模糊匹配,适合“不包含子串”,但如果你只是想确认某个字符**完全没出现过**(比如邮箱字段不能含空格),CHARINDEX(SQL Server)或 LOCATE(MySQL)更直白、无歧义。
示例(SQL Server):WHERE CHARINDEX(' ', email) = 0
示例(MySQL):WHERE LOCATE(' ', email) = 0
优势:
- 语义清晰:0 就是“没找到”,不是模式匹配逻辑
- 不触发通配符解析,性能略优(尤其字段有索引时)
- 不受
ESCAPE或转义字符干扰
多个排除字符要拆开写,别指望一个 NOT LIKE 搞定
想查“name 不含 A 且不含 B”,不能写 NOT LIKE '%A%B%' —— 这实际是“不同时含 A 和 B 且中间有任意字符”,逻辑完全不对。
正确写法是叠加条件:
- SQL Server:
WHERE CHARINDEX('A', name) = 0 AND CHARINDEX('B', name) = 0 - MySQL:
WHERE LOCATE('A', name) = 0 AND LOCATE('B', name) = 0 - 通用兼容写法(稍慢):
WHERE name NOT LIKE '%A%' AND name NOT LIKE '%B%'
注意:多个 NOT LIKE 在大数据量下可能比函数方式慢,因无法有效利用索引。
REGEXP / RLIKE 能力强,但别在简单场景滥用
MySQL 支持 NOT REGEXP 'A|B|C',PostgreSQL 用 !~ 'A|B|C',SQL Server 2022+ 可借 STRING_SPLIT + NOT EXISTS 模拟,但这些属于进阶方案。
除非你真需要:
- 排除符合某种正则规律的字符串(如“不以数字开头”)
- 动态构建排除规则(如从配置表读取黑名单正则)
- 已有正则知识沉淀,团队维护成本可控
否则,对单字符或固定子串的排除,CHARINDEX/LOCATE 或拆开的 NOT LIKE 更轻量、易读、易调试。
真正容易被忽略的是:不同数据库对空字符串 '' 和 NULL 的行为差异——哪怕写了 IS NOT NULL,也得确认源数据里有没有全空格或不可见字符混入。










