%匹配零个或多个任意字符,_仅匹配恰好一个任意字符;例如'a_c'匹配'abc'但不匹配'ac'或'abbc',而'a%c'两者均匹配。

LIKE语句中%和_通配符的实际行为差异
LIKE不是正则匹配,%和_有严格定义:%匹配零个或多个任意字符,_只匹配**恰好一个**任意字符。比如'a_c'能匹配'abc'或'a2c',但不匹配'ac'或'abbc';而'a%c'两者都匹配。
常见错误是把_当“可选字符”用,结果漏掉数据。如果真要匹配“a后跟0或1个字符再跟c”,得写成'ac' OR 'a_c',不能只靠_。
中文、空格、特殊字符导致LIKE失效的典型场景
数据库默认排序规则(collation)影响大小写和空格处理。例如MySQL用utf8mb4_0900_as_cs时,'ABC' LIKE 'abc'返回FALSE;而utf8mb4_general_ci会忽略大小写。
更隐蔽的问题是尾部空格:SQL标准规定字符串比较会右补空格,所以'hello' LIKE 'hello '在多数引擎里为TRUE——但用户通常不期望这样。解决方法包括:
- 用
RTRIM()预处理字段或参数,如RTRIM(name) LIKE '张%' - 改用
REGEXP(MySQL)或~(PostgreSQL)避开空格隐式处理 - 确认字段定义是否含
CHAR类型(固定长度,自动补空格),优先用VARCHAR
LIKE查询性能差的根本原因和绕过方式
前导通配符(如LIKE '%关键词'或LIKE '%关键%')会导致索引失效,全表扫描不可避免。即使加了B-tree索引,也只对'关键词%'这种左匹配有效。
真实业务中可考虑:
- 用全文索引替代:MySQL的
FULLTEXT,PostgreSQL的tsvector,支持分词和权重 - 冗余字段预处理:比如提取姓名首字母存为
name_first,查姓氏时用name_first = '张'走索引 - 限制模糊范围:避免无约束
%,改用LEFT(name, 2) = '张三'或SUBSTRING(name, 1, 2) = '张三',仍可命中索引
ESCAPE自定义转义符的必要性与常见误用
当要匹配字面量%或_时,必须用ESCAPE指定转义字符,否则数据库直接按通配符解析。例如查含下划线的用户名'user_name',写WHERE name LIKE 'user\_name' ESCAPE '\'才对。
容易踩的坑:
- 忘了写
ESCAPE子句,只加反斜杠,结果'user\_name'被当成'user' + 任意单字符 + 'name' - 选错转义符本身含特殊含义,比如用
'%'作转义符:LIKE '100\%' ESCAPE '%'语法错误,因为%不能作转义符 - 不同数据库默认转义符不同(MySQL默认无,SQL Server默认
\),跨库迁移时必须显式声明
最稳妥的做法是始终显式写ESCAPE,并选一个在业务数据中几乎不会出现的字符,比如CHAR(1)对应的0x01,或简单用'$'。

















