like语句中下划线_匹配且仅匹配一个任意字符,百分号%匹配零个或多个任意字符;二者均为固定规则的通配符,非智能模糊搜索。

LIKE 语句中下划线 _ 和百分号 % 的实际含义
MySQL 的 LIKE 不是“模糊匹配”字面意思的智能搜索,而是基于**单字符通配符 _ 和多字符通配符 %** 的字符串模式匹配。它不支持正则语法(除非用 REGEXP),也不做分词或相似度计算。
常见误解:以为 name LIKE '张_' 能匹配“张三丰”,其实只能匹配“张X”(两个字);name LIKE '张%' 才能匹配“张三”“张三丰”“张小花”等所有以“张”开头的字符串。
-
_严格匹配且仅匹配一个任意字符(不能是空、不能跳过) -
%匹配零个或多个任意字符(包括空字符串) - 如果要查真实下划线(比如字段值为
user_name),必须转义:LIKE '%\_name' ESCAPE '\' - 默认大小写敏感性取决于字段的 collation;若用
utf8mb4_general_ci等 _ci 结尾的排序规则,则不区分大小写
中文字段用 LIKE 查询慢?索引是否生效
LIKE 查询能否走索引,只和**通配符位置**有关,和是否中文无关。只要模式是前缀匹配(LIKE 'abc%'),且字段有 B-tree 索引,就能用上索引。
但一旦开头带 % 或 _(如 LIKE '%王%' 或 LIKE '_明'),就无法使用索引的有序结构,只能全表扫描——这对百万级中文用户表,可能直接卡死查询。
- 能走索引:
WHERE name LIKE '李%'、WHERE code LIKE 'A2024%' - 不能走索引:
WHERE name LIKE '%伟'、WHERE title LIKE '%数据库%'、WHERE tag LIKE '_SQL' - 复合索引中,LIKE 只能用于最左前缀部分;例如索引是
(city, name),那么WHERE city = '北京' AND name LIKE '刘%'可用索引,但WHERE name LIKE '刘%'单独用就失效
想查“包含某中文子串”,又不想全表扫描怎么办
纯靠 LIKE '%关键词%' 在大数据量下不可行。替代方案不是换写法,而是换思路:
- 用全文索引(
FULLTEXT)+MATCH ... AGAINST:适合文章、简介类长文本,需字段类型为TEXT或VARCHAR,且建表时加FULLTEXT(name);注意中文需 MySQL 5.7.6+ + ngram 插件,或 8.0+ 内置 ngram parser - 导出到 Elasticsearch / Meilisearch:对中文分词、拼音、同义词支持更好,适合搜索场景
- 业务层加冗余字段:例如从
title中提取关键词生成keywords字段(逗号分隔),再用FIND_IN_SET('mysql', keywords)或keywords LIKE '%mysql%'—— 这种方式可控但需维护一致性 - 避免在 OLTP 主库跑模糊搜索:把日志/用户行为数据同步到专用搜索库,主库只做精确查询(ID、状态、时间范围等)
LIKE 查询结果为空却没报错?检查这几点
返回空结果不等于出错,但常因隐式转换或边界条件被忽略:
- 字段含前后空格:
TRIM()没处理,导致' 张三 '不匹配'张三';建议查询时用TRIM(name) LIKE '张%',或建生成列索引 - 字段为
NULL:name LIKE '%a%'对NULL值永远返回NULL(不是TRUE/FALSE),所以不会出现在结果里;需要显式加OR name IS NULL控制逻辑 - 字符集不一致:比如连接时用
latin1,但字段是utf8mb4,中文会变成乱码,导致匹配失败;检查SHOW VARIABLES LIKE 'character_set%';和表定义 - 参数拼接错误:应用层拼 SQL 时忘了加引号,如写成
WHERE name LIKE $keyword(PHP),实际执行成了WHERE name LIKE 张三,触发语法错误或隐式转换
最常被忽略的是 NULL 处理和空格——这两个问题在线上查半天,往往就差一个 COALESCE(TRIM(name), '')。










