背景:今天需要对数据库检索一下 MySQL 数据库用户表当中非法昵称的用户数
合法昵称定义:中文(不包括全角符号)、日文、英文字母(a-z 及 A-Z)、数字(0-9)及下划线(_)
因此有如下 SQL 语句
SELECT COUNT(*)
FROM `user`
WHERE
`username`
NOT REGEXP
'^[A-Za-z0-9_\\x{4e00}-\\x{9fa5}\\x{3040}-\\x{309f}\\x{30a0}-\\x{30ff}\\x{31f0}-\\x{31ff}]+$';
-- 说明:
-- 英文字母及数字、下划线
-- A-Za-z0-9_
-- 中文 Unicode 范围
-- \x{4e00}-\x{9fa5}
-- 参考:https://www.xuebuyuan.com/363261.html
-- 日方 Unicode 范围
-- \x{3040}-\x{309f}
-- \x{30a0}-\x{30ff}
-- \x{31f0}-\x{31ff}
-- 参考:http://www.cnblogs.com/csguo/p/7401874.html
-- http://tool.chinaz.com/tools/unicode.aspx
上述 SQL 在 MySQL 8.0 版本运行正常并跑出结果 41755 条
但在 MySQL 5.7 及 5.6 版本运行遇到报错:
Got error ‘invalid character range’ from regexp
检索了一圈有说是 MySQL 的 Bug,官网上也找不到类似的试例
但看到 https://bugs.mysql.com/bug.php?id=37892 这篇后受了启发
何不直接写中文/日方的文字,交由 MySQL 来解析试试
故有以下 SQL
SELECT count(*)
FROM `user`
WHERE
`username`
NOT REGEXP
'^[A-Za-z0-9_一-龥ぁ-ゞァ-ヾ]+$';
-- 说明
-- 英文字母及数字、下划线
-- A-Za-z0-9_
-- 中文范围
-- 一-龥 对应 Unicode \x{4e00}-\x{9fa5}
-- 日文范围
-- ぁ-ゞ对应 Unicode \x{3040}-\x{309f},但作了取舍,因为有些 Unicode 解析出来拷到 MySQL 客户端上后变成奇怪的乱码
-- ァ-ヾ 对应 Unicode \x{30a0}-\x{30ff},也作了取舍
-- \x{31f0}-\x{31ff} 由于作为日文中的扩展经 Unicode 转字符出来后拷到 MySQL 客户端上也是乱码,故进行割舍
-- 附 Unicode 转换成字符地址 http://tool.chinaz.com/tools/unicode.aspx
运行上述 SQL 后,在 MySQL 8.0 得到相同结果(41755),在 5.7/5.6 也能顺利跑出结果