LIKE 是什么
LIKE 做模式匹配:百分号匹配任意长度字符串(包括零个字符),下划线匹配恰好一个字符。性能上有一条硬规则:只有前缀模式('abc%')能有效利用普通 B 树索引,前后都加百分号基本等同全表扫描。匹配字面量的百分号或下划线时必须转义,用 ESCAPE 子句显式指定转义符比依赖默认反斜杠更可控。需要包含关键词式的全文检索时,应该评估全文索引、pg_trgm 或独立搜索引擎,而不是反复扫大表。
基本信息
| 百分号 % | 匹配任意长度字符串,包含零个字符 |
|---|---|
| 下划线 _ | 匹配恰好一个字符 |
| ESCAPE 子句 | 自定义转义符,如 LIKE '100!%' ESCAPE '!' |
| 索引能力 | 只有前缀模式能有效使用 B 树索引 |
| 大小写 | 取决于排序规则:MySQL 默认不区分,PostgreSQL 区分 |
| 适用平台 | 标准 SQL,MySQL 8.0 与 PostgreSQL 均支持 |
典型使用场景
- 前缀搜索:按姓名首字母、编号前缀筛选,能走索引
- 数据清洗:找出包含异常字符、多余空格、全角符号的记录
- 粗粒度模糊查找:只知道片段时先定位范围
- 黑名单匹配:查找内容里包含敏感词的记录,数据量大时改用全文索引
- 格式粗校验:用模式检查编号是否符合基本形状,严格校验交给应用层
- 排除测试数据:NOT LIKE '%test%' 过滤测试账号
示例
示例
SELECT * FROM users WHERE name LIKE 'Li%'; # 前缀匹配,能用索引
SELECT * FROM users WHERE name LIKE '%son'; # 后缀匹配,通常全表扫描
SELECT * FROM users WHERE code LIKE 'A_1'; # 下划线匹配一个字符
-- 匹配字面量百分号:用 ESCAPE 指定转义符
SELECT * FROM rates WHERE label LIKE '100!%' ESCAPE '!';
-- PostgreSQL 可用 ILIKE 做不区分大小写的匹配
SELECT * FROM users WHERE name ILIKE 'li%';模式与索引能力
| 模式 | 能否用索引 | 说明 |
|---|---|---|
| 'abc%' | 可以 | 前缀匹配,符合 B 树最左前缀 |
| '%abc' | 不可以 | 后缀匹配需要逐行比较 |
| '%abc%' | 不可以 | 典型全表扫描模式 |
| 'a_c' | 一般不可以 | 下划线是通配符,前缀不固定 |
| 联合索引首列做前缀 | 可以 | 条件是前缀即可命中该索引 |
| ESCAPE 后的字面量引号 | 视写法而定 | 转义符本身不影响索引选择 |
需要包含关键词式检索时,正确方向是全文索引(MySQL FULLTEXT、PostgreSQL tsvector)或外部搜索引擎,而不是给 LIKE '%x%' 加索引。
MySQL 中反斜杠默认是 LIKE 的转义符,匹配含反斜杠的内容容易出错;显式写 ESCAPE 更可控,也便于跨库迁移。
PostgreSQL 的 LIKE 区分大小写,MySQL 的默认排序规则不区分;跨库 SQL 若依赖大小写行为,应显式使用 ILIKE 或调整排序规则。
PostgreSQL 可以给 pg_trgm 扩展建 GIN 或 GiST 索引来加速 %abc% 这类包含匹配,代价是索引体积与写入开销都会上升。
使用要点
- 把通配符放在末尾:'abc%' 能用索引,'%abc' 与 '%abc%' 不能
- 能确定前缀就用前缀:把已知部分提到最左侧
- 用户输入里的 % 和 _ 要转义,否则会被当作通配符放大匹配范围
- 参数化查询里拼 LIKE 时用 CONCAT('%', ?, '%') 而不是手工拼字符串
- 模糊匹配结果用于展示时要限制条数,避免一次返回大量数据
- 清洗场景先备份:LIKE 命中的记录往往需要批量修数据
等值条件与前缀条件可以写在一起(code = 'A1' OR code LIKE 'A1%'),但 OR 会让两侧都难以优先走索引,能拆成两条查询合并就拆开。
转义符本身也要能被搜索:在 ESCAPE '!' 下匹配字面量感叹号要写 '!!',这类细节在批量清洗脚本里最容易出错,写完先用几条样例数据验证。