下划线“_”在sql like中是单字符通配符,必须用escape子句显式转义(如like 'a_b' escape '')才能匹配字面下划线;insert时无需转义,仅查询时like需处理,跨库推荐用安全转义符如!。

SQL下划线_通配符必须转义才能匹配字面意义的下划线
直接写 WHERE col LIKE '%_%' 会把 _ 当作单字符通配符,不是查带下划线的字符串。想查真实存在的下划线(比如用户名 user_name),必须显式转义。
不同数据库转义方式不一致,常见方案:
- MySQL / PostgreSQL:用
ESCAPE指定转义字符,例如LIKE '%_%' ESCAPE '' - SQL Server:默认支持反斜杠转义,也可自定义,如
LIKE '%_%' ESCAPE '';若用方括号,LIKE '%[_]%'也行 - Oracle:同样依赖
ESCAPE,LIKE '%_%' ESCAPE ''是标准写法
注意:反斜杠 在某些客户端(如 Python 的 sqlite3、Java JDBC)里本身要被语言层转义,可能需要写成 '%\_%' 或改用其他转义符(如 !)避免歧义。
用ESCAPE指定非反斜杠转义符更安全
反斜杠容易引发双重转义问题,尤其在嵌入到应用代码中时。推荐换一个生僻字符作转义符,比如 ! 或 #,降低出错概率。
示例(通用写法):
SELECT * FROM users WHERE username LIKE '%!_%' ESCAPE '!';
这样只要原数据里不含 !,就几乎不会冲突。对应地,查 api_v1 就写 LIKE 'api!_v1' ESCAPE '!'。
要点:
-
ESCAPE后只能跟单个字符,不能是字符串 - 转义符本身如果要出现在模式中,需写两次:
'%!%%' ESCAPE '!'表示匹配%字符 - SQLite 默认不支持
ESCAPE(3.16+ 才支持),旧版本得用INSTR()或正则替代
_和%混用时位置与数量必须严格对应
_ 匹配且仅匹配一个任意字符(包括空格、数字、字母、符号),% 匹配零个或多个任意字符。两者混用极易误判结果。
比如查形如 a_b 的三字符字符串(a、任意1字符、b):
- ✅ 正确:
LIKE 'a_b'(刚好3位,中间是任意单字符) - ❌ 错误:
LIKE 'a%b'会匹配ab、a123b、a b等任意长度 - ❌ 错误:
LIKE 'a_b%'会匹配a_b、a_bc、a_b123—— 多余内容没被约束
真实场景如查邮箱前缀为 test_xxx@(x 为单数字):LIKE 'test_[0-9]@%' ESCAPE '' 不行 —— LIKE 不支持字符类,得拆成 LIKE 'test_0@%' OR LIKE 'test_1@%' ...,或改用正则函数(如 PostgreSQL 的 ~)。
性能隐患:LIKE带前导通配符无法走索引
只要模式以 % 或 _ 开头(如 LIKE '_abc' 或 LIKE '%_abc'),绝大多数数据库无法使用 B-tree 索引加速,会触发全表扫描。
优化思路:
- 尽量让模式以常量开头:
LIKE 'user_name%'可走索引(前缀匹配) - 对高频模糊查询字段,考虑生成“反向字段”并建索引,如
username_rev存emanresu,查后缀时用LIKE 'resu%' - 全文索引或专门的搜索扩展(如 PostgreSQL 的
pg_trgm)更适合复杂模糊场景
别低估 _ 的开销——它虽只占一位,但和 % 一样破坏索引可用性,只要出现在最左位置,就等于放弃索引。










