前缀匹配必须用LIKE 'prefix%',因B-Tree索引仅支持从左到右的前缀查找;'%prefix'为后缀匹配,导致全表扫描;需注意转义、排序规则及空格处理。

LIKE语句中前缀匹配的写法必须用'prefix%',不能用'%prefix'
前缀匹配的本质是“开头一致”,SQL标准里LIKE的通配符%表示任意长度字符(包括零个),所以要查以'abc'开头的数据,必须写成WHERE column LIKE 'abc%'。写成'%abc'是后缀匹配,'%abc%'才是包含匹配——这点错一点,结果就全偏了。
常见错误现象:SELECT * FROM users WHERE name LIKE '%admin' 返回一堆superadmin、rootadmin,但漏掉了admin_001、admin_test这些真正符合“前缀”需求的记录。
-
'abc%'→ 匹配abc、abcdef、abc_2024 -
'%abc'→ 匹配xyzabc、admin(如果列值是admin,但admin不以abc结尾,就不会命中) -
'abc_'→ 下划线_只匹配单个任意字符,适合固定长度前缀场景,比如查'A001'、'A002'这类编号
注意大小写敏感性:MySQL默认不区分,PostgreSQL和SQL Server默认区分
在PostgreSQL中执行WHERE name LIKE 'Admin%',不会命中'admin_user';而同样语句在MySQL(默认utf8mb4_general_ci)里会命中。这不是BUG,是排序规则(collation)决定的。
解决方法不是硬改数据,而是显式控制:
- MySQL想强制区分:加
BINARY,如WHERE BINARY name LIKE 'Admin%' - PostgreSQL想忽略大小写:用
ILIKE代替LIKE,或写WHERE LOWER(name) LIKE LOWER('admin%') - SQL Server可用
COLLATE SQL_Latin1_General_CP1_CI_AS临时切换排序规则
前缀查询性能差?给字段加前缀索引或函数索引
单纯LIKE 'abc%'可以走B-tree索引(前提是没用函数包裹、没前置%),但一旦写成LOWER(name) LIKE 'admin%'或CONCAT('pre_', name) LIKE 'pre_admin%',索引就失效了。
优化路径很直接:
- 对纯前缀场景(
name LIKE 'abc%'),确保name字段有普通B-tree索引即可 - 对大小写不敏感前缀查询(如
LOWER(name) LIKE 'abc%'),PostgreSQL/MySQL 8.0+支持函数索引:CREATE INDEX idx_name_lower ON users (LOWER(name)) - MySQL若版本较老,可冗余一个
name_lower字段存小写值并建索引,应用层同步维护
特殊字符如_、%本身要当字面量查?必须用ESCAPE
如果真要查用户名为'admin_2024'的用户,写WHERE name LIKE 'admin_%'会把'admin123'、'adminX'全捞出来——因为下划线是通配符。同理,查含百分号的字符串(如折扣码'50%OFF')也会出错。
正确做法是定义转义字符,并在字面量前加它:
-
WHERE name LIKE 'admin\_%' ESCAPE '\'→ 匹配admin_2024,不匹配adminX -
WHERE code LIKE '50\%OFF' ESCAPE '\'→ 精确匹配50%OFF - 某些数据库支持
ESCAPE '$'等其他符号,只要前后一致就行
没声明ESCAPE却用了转义字符,不同数据库行为不一:MySQL可能静默忽略,PostgreSQL直接报错ERROR: invalid escape string。

















