sql标准规定“_”严格匹配且仅匹配一个任意字符,如'a_c'匹配'abc'或'a c'但不匹配'ac'或'abcd';误用'object_%'会因_匹配任意单字符而错误包含'objectanything',正确做法是用escape指定转义符(如'object!_%' escape '!')或sql server的'object[_]%'。

它不是“为什么代表”,而是SQL标准就这么定的——_ 就是单字符通配符,没得商量。你真正该关心的是:怎么用对、怎么避坑、怎么查到真实下划线。
LIKE里的_到底匹配什么
它严格匹配**一个且仅一个**字符,不管这个字符是字母、数字、空格、符号,甚至不可见字符(比如制表符)。不跳过、不扩展、不忽略。
-
LIKE 'a_c'→ 匹配'abc'、'a c'、'a_c',但不匹配'ac'(缺一位)或'abcd'(多一位) -
LIKE '_o__'→ 必须是4位字符串,第2位是o,其他三位任意,比如'tofu'✅,'go'❌ - 连续写多个
_就是连续占位:'___'= 三位任意字符串,不是“至少三位”
为什么LIKE 'object_%'会误匹配objectAnything
因为_在这里不是字面意义的下划线,而是通配符——它匹配了A这个字符,%再吃掉后面所有内容。
- 错误写法:
WHERE type LIKE 'object_%'→ 实际含义是 “object + 任一字符 + 任意后续内容” - 正确写法(MySQL/PostgreSQL/Oracle):
WHERE type LIKE 'object!_%' ESCAPE '!'→ 这样才真查带下划线的object_test - SQL Server 可选:
WHERE type LIKE 'object[_]%',方括号只在 SQL Server 有效 - 别硬套反斜杠:
'object\_%'在 Python 的sqlite3或 JDBC 里可能被语言层先吃掉一次,变成'object_%',又变回通配符
转义符选哪个更稳
别用\,尤其当SQL嵌在应用代码里时。它太容易被双重转义搞崩。
-
ESCAPE后面只能跟**单个字符**,不能是字符串 - 推荐用生僻符号,比如
!或#:LIKE 'api!_v1' ESCAPE '!' - 如果数据里真含
!,那就换#;实在都冲突,就用正则(如 PostgreSQL 的~)或字符串函数(如INSTR(col, '_') > 0)兜底 - SQLite 旧版本(ESCAPE,得绕开
LIKE,直接用INSTR()或启用REGEXP扩展
性能上最容易被忽略的一点
LIKE 模式只要以 _ 或 % 开头,比如 LIKE '_user' 或 LIKE '%_user',B-tree 索引基本就废了——全表扫描等着你。
- 能写成
LIKE 'user_%'就别写LIKE '%user%',前者可走前缀索引 -
_在中间或末尾不影响索引使用,但前提是前面有确定前缀 - 查邮箱前缀
test_0@这种固定结构,比LIKE 'test[_]%' ESCAPE '['更快,也比正则稳妥
最常翻车的地方不在语法,而在把 _ 当字面量用却忘了转义,或者以为加个 ESCAPE '\' 就万事大吉——结果语言层和数据库层各吃一次反斜杠,最后还是通配符。











