%代表零个、一个或多个任意字符,可匹配空串、单字符或混合字符串,但置于开头会导致索引失效而引发全表扫描;其行为与字符集无关,中文场景无需写%%,且与_共用时_的单字符约束优先级更高。

百分号 % 是零个、一个或多个任意字符的占位符
它不表示“大概”“差不多”,而是严格语义上的长度可变匹配:% 能匹配空字符串、单字符、中文、英文、数字、符号,甚至混合组合,只要位置对得上。比如 LIKE 'a%z' 会命中 'az'(中间零字符)、'abz'、'a123xyz',但不会命中 'za' 或 'a_bz'(除非下划线是真实字符)。
% 放在开头会导致索引失效,查得慢
数据库优化器通常只能利用前缀固定的模式走索引。LIKE 'abc%' 可能用上索引;但 LIKE '%abc' 几乎必然触发全表扫描——MySQL、PostgreSQL、SQL Server 都如此。这不是配置问题,是 B+ 树索引结构决定的。
- 想查“以‘订单’结尾的备注”,别写
remark LIKE '%订单',改用RIGHT(remark, 2) = '订单'或加函数索引(如 MySQL 8.0+ 的CREATE INDEX idx_remark_suffix ON t ((RIGHT(remark, 2)))) - 查“含‘测试’的标题”,
title LIKE '%测试%'没法优化,若频次高,考虑全文索引或提前冗余字段(如has_test TINYINT) - 用
EXPLAIN看执行计划:如果type是ALL或index,基本说明没走有效索引
中文场景下 % 不需要双写 %%
网上有些旧资料说“中文要写 %%”,这是错误认知。SQL 标准和所有主流数据库(MySQL、PostgreSQL、SQL Server、Oracle)中,% 的行为与字符集无关,UTF-8 或 GBK 下都一样匹配任意长度字节序列——只要字段类型是 VARCHAR/TEXT 且校对规则支持中文比较。
- 正确写法:
name LIKE '%张%'→ 匹配“张三”“李张明”“小张老师” - 错误写法:
name LIKE '%%张%%'→ 多余,语义不变但易引发误解 - 真正要注意的是:如果字段是
CHAR类型且含尾部空格,LIKE会按填充后长度比对,此时可能需要RTRIM()预处理
当 % 和 _ 混用时,长度约束立即生效
% 管“多长都行”,_ 管“必须刚好一位”,二者共存时,_ 的强制性优先级更高。比如 LIKE 'A_%B' 表示:首字符 A,第二位是任意单字符,最后以 B 结尾;它不会匹配 'AB'(缺了 _ 对应的那一位),也不会匹配 'AXYZB'(% 允许中间多字符,但整体结构仍需满足 A + 一字符 + … + B)。
- 查“4位纯数字验证码”:用
code LIKE '____'(四个_),不是code LIKE '%'——后者会拉回所有非空值 - 查“手机号 138 开头 + 4 位数字”:写
phone LIKE '138____',不能写'138%',否则可能拿到完整 11 位号码 - 查“邮箱域名是 gmail.com”:写
email LIKE '%@gmail.com'安全;但若字段有空格或大小写混杂,得先LOWER(TRIM(email))再匹配
% 的“任意长度”包含零长度,这在边界 case 中常导致意外匹配——比如 status LIKE '%' 实际等价于 status IS NOT NULL AND status != ''(取决于空字符串是否被视为空值),而不是“无条件通过”。










