regexp和rlike完全等价,可互换使用;二者底层调用同一icu正则引擎,返回1(匹配)或0(不匹配),区别仅在于命名习惯和团队偏好,mysql 8.0+才支持icu引擎及完整posix ere特性。

REGEXP 做基础复杂匹配,但别指望它支持反向引用、d 或非贪婪量词——这些要么报错,要么行为不可靠。
MySQL 的 REGEXP 和 RLIKE 到底能不能互换?
能,完全等价。二者底层调用同一 ICU 正则引擎,返回值都是 1(匹配)或 0(不匹配)。选哪个纯看团队习惯:RLIKE 在日志分析类 SQL 里读起来更自然,REGEXP 更常见于建模语句。但注意:MySQL 8.0 之前用的是 Henry Spencer 库,功能弱、不支持 Unicode;8.0+ 才切到 ICU,才真正可用。
哪些正则写法在 MySQL 里会直接报错或失效?
最常踩坑的是把 PCRE/JavaScript 风格正则原样粘贴进来:
-
d、w、s—— 必须写成[0-9]、[a-zA-Z0-9_]、[[:space:]] - 反向引用如
(w+)—— 语法不报错,但匹配逻辑不稳定,实际应避免 - 非贪婪量词
.*?—— MySQL 全部按贪婪处理,.*?等价于.* - 断言
(?=...)或(? —— 直接报错 <code>ERROR 1139 (HY000): Got error 'invalid character class' from regexp
实操建议:用 [[:digit:]] 替代 d,用 [[:alpha:]] 替代 [a-zA-Z],兼容性更稳。
怎么安全地匹配“独立单词”,比如 CSV 字段里的 php?
别用 tags REGEXP '(^|,)php(,|$)' —— 它会在 hyperphp 或 php7 上误判。MySQL 不支持 ,得手动模拟词边界:
WHERE tags REGEXP '(^|[^a-zA-Z0-9_])php([^a-zA-Z0-9_]|$)'-
(^|[^a-zA-Z0-9_])表示开头 或 非单词字符(防xphp) -
([^a-zA-Z0-9_]|$)表示结尾 或 非单词字符(防phpx) - 如果字段是
utf8mb4+ MySQL 8.0+,可用[[:punct:]]替代[^a-zA-Z0-9_],覆盖标点更准
性能提醒:这种正则无法走索引,大表务必加前置条件过滤,比如先 WHERE status = 'active' 再做正则。
想从字符串里提取子串,比如邮箱域名,怎么办?
MySQL 原生 REGEXP 只能判断匹配与否,不能提取。直到 8.0.30+ 才有 REGEXP_SUBSTR(),但限制多:
- 只支持单次提取,
occurrence参数从1开始,不支持全局标志g - 写
REGEXP_SUBSTR(email, '@([^.]+)\.', 1, 1, NULL, 1)想取域名,但 MySQL 不支持捕获组引用(第 6 参数),实际无效 - 更稳妥的路是拆解:
SUBSTRING_INDEX(SUBSTRING_INDEX(email, '@', -1), '.', 1)+ 长度校验 - 真要复杂提取,优先在应用层(Python/Java)做,再把结果传入 SQL
真正容易被忽略的是:哪怕用了 REGEXP_SUBSTR,只要 pattern 含 . 或 * 就大概率触发全表扫描——它本质上仍是逐行计算,不是索引操作。











