LIKE和REGEXP语义不同:LIKE '%str%'是全字段模式匹配,不支持索引;REGEXP 'str'是子串存在判断,但性能更差;简单子串查找应优先用LOCATE或INSTR。

直接说结论:LIKE 和 REGEXP 都能判断字段是否包含特定字符串,但语义、性能、匹配逻辑完全不同——别混用,也别默认选 LIKE。
LIKE '%str%' 是「全字段匹配模式」,不是「子串存在判断」
LIKE 的设计本质是「字段值是否符合某个完整模式」,哪怕你写 LIKE '%str%',MySQL 仍会把整个字段值当作一个整体去比对这个通配模式。它不关心“str”是不是独立子串,只看能否套进 %str% 这个框架里。
- 字段值为
'astrb'→ 匹配成功 - 字段值为
'a str b'(含空格)→ 同样匹配成功 - 字段值为
NULL→ 永远不匹配(LIKE对NULL返回UNKNOWN,被当FALSE处理) - 字段有 B-tree 索引,但
LIKE '%str%'开头是%→ 索引失效,必然全表扫描
REGEXP 'str' 是真正的「子串存在判断」
REGEXP 默认行为就是「只要字段值中任意位置出现该字符串,就返回真」,不需要前后加 .*,也不需要考虑字段是否被完整覆盖。
-
name REGEXP 'john'→ 匹配'john'、'Johnny'、'michael johnson' - 想严格匹配开头?加
^:name REGEXP '^john' - 想严格匹配结尾?加
$:name REGEXP 'john$' - 注意:
REGEXP在 MySQL 8.0+ 区分大小写取决于字段的 collation;若需忽略大小写,用REGEXP BINARY 'John'反而强制区分,应改用REGEXP '(?i)john'或确保 collation 为_ci后缀
性能差异大到必须提前决策
在百万级数据上,LIKE 'str%'(前缀匹配)可能走索引,毫秒级;LIKE '%str%' 和 REGEXP 'str' 基本都走全表扫描,但后者额外消耗 CPU 做正则引擎解析,实测慢 20%~50%。
- 仅需判断「是否含某固定字符串」→ 优先用
LOCATE('str', column) > 0或INSTR(column, 'str') > 0,它们比REGEXP轻量,且语义更直白 - 需要模糊但非正则逻辑(如「以 A 开头、长度为 5、第 3 位是数字」)→
LIKE更合适,写法短、优化器识别稳定 - 真正需要「字符类、重复次数、分组或分支」→ 才上
REGEXP,例如phone REGEXP '^[1-9][0-9]{10}$' -
FULLTEXT不在此列,它适合自然语言搜索,对单个短字符串的「存在性判断」反而更重、更不准
容易被忽略的细节:转义与特殊字符
LIKE 和 REGEXP 对特殊字符的处理规则完全独立,不能套用同一套转义习惯。
-
LIKE中%和_是通配符,要查字面意义的%,得写LIKE '%' ESCAPE '',且必须显式声明ESCAPE -
REGEXP中.、*、+、?、^、$、|、[、]都是元字符,要查字面意义的点号,得写REGEXP 'a\.b'(两个反斜杠,因 SQL 字符串先解析一次) - 最常踩坑:
WHERE name LIKE 'a_b'本意是查'a_b',结果却匹配了'aab'、'axb'—— 因为_没转义
真正麻烦的从来不是语法怎么写,而是你没想清楚:到底是要「字段长得像某个模板」,还是「字段里有没有这个片段」。选错操作符,后面加索引、调参数、换引擎都是白忙。











