MySQL中REGEXP匹配中文需用[\u4e00-\u9fff]且collation必须为utf8mb4_unicode_ci等支持Unicode的规则,否则静默失效;兼容兜底方案是LENGTH()!=CHAR_LENGTH()。

MySQL中REGEXP匹配中文必须用双反斜杠u且字段collation要支持Unicode
直接写 name REGEXP '[u4e00-u9fa5]' 在 MySQL 8.0+ 里可能“看起来能跑”,但实际静默失效——不是语法错,而是 collation 不匹配。utf8mb4_general_ci 这类旧排序规则根本不识别 Unicode 码点范围,REGEXP 会退化为字面匹配,漏掉绝大多数汉字。
真正生效的组合是:
-
REGEXP '[\u4e00-\u9fff]'(注意:SQL 字符串里必须写两个反斜杠,最终被解析成一个u) - 字段或表的 collation 必须是
utf8mb4_unicode_ci、utf8mb4_0900_as_cs等支持 Unicode 属性的规则 - 字符集必须为
utf8mb4,连接层也要设为utf8mb4(比如 JDBC 的useUnicode=true&characterEncoding=utf8mb4)
别用 [一-龥]:MySQL 把它当 GBK 字符集下的字面区间处理,覆盖不全,还容易因 collation 差异完全不触发。
CHAR_LENGTH() ≠ LENGTH() 是最兼容的兜底方案
当没权限改 collation、或数据库版本太老(如 MySQL 5.6)、或字段值极短(如单字节字段)时,正则不可靠,这时用长度差更稳。
原理很简单:在 utf8mb4 下,ASCII 字符(a-z、0-9、标点)占 1 字节,而中文基本都占 3 字节。所以:
-
CHAR_LENGTH(content)返回字符个数(“你好”=2) -
LENGTH(content)返回字节数(“你好”=6) - 只要
LENGTH(content) != CHAR_LENGTH(content),就说明含多字节字符(大概率是中文)
注意:这个方法会把 emoji、日文、韩文、全角标点也一并捕获,不是纯中文专用;但它不依赖 collation,也不怕 NULL 或空字符串,适合快速筛脏数据。
LIKE N'%[一-鿿]%' 在 SQL Server 更可靠,但在 MySQL 中慎用
MySQL 的 LIKE 对 Unicode 范围支持极弱,LIKE '%[一-龥]%' 实际上只在 latin1 字符集下按字节比较,结果不可控。强行用会误判、漏判,甚至因字段长度大导致全表扫描拖慢查询。
如果你看到有人这么写,大概率是在迁移到 MySQL 前从 SQL Server 抄过来的——SQL Server 需要 N'' + COLLATE ..._SC_UTF8 才能生效,而 MySQL 完全不认这套。在 MySQL 里坚持用 REGEXP 或长度差,别碰 LIKE 做中文判断。
为什么 u9fff 比 u9fa5 更值得推荐
U+4E00–U+9FA5 是《康熙字典》常用汉字区,但现代系统里大量出现扩展 A 区(U+3400–U+4DBF)、扩展 B 区(U+20000–U+2A6DF)甚至 U+9FFF(含「〇」「〆」「々」等兼容汉字)。只写 [u4e00-u9fa5] 会漏掉「?」「﨑」「鱻」这类三叠字,以及很多人名、地名用字。
生产环境建议统一用 [u4e00-u9fff](覆盖基本区+扩展A/B前段),或更保守地加一层 |[u3400-u4dbf]|[U00020000-U0002a6df](需 MySQL 8.0+ 支持四字节 Unicode 字面量)。不过后者对 collation 和连接配置要求更高,日常清洗用 [u4e00-u9fff] 已够用。
最容易被忽略的是 collation —— 即使正则写对、字符集设对,只要字段定义里还是 utf8mb4_general_ci,整个条件就形同虚设。


















