MySQL 查询含中文字符数据,让人有点困惑了

拿到一份数据,做数据清洗时遇到了奇怪的问题,RT,不清楚是 MySQL 是正则匹配比较特殊还是我使用的姿势不对。

MySQL 版本 5.7, 编码 utf8mb4

正则匹配中文我一般用下面两种表达式,后者为前者对应的 unicode,用正则测试工具没什么问题。

[一-龥]
[\u4e00-\u9fa5]

但在 MySQL 中这两种正则写法查询结果却完全不一样,也搜到了一些不同的写法,基本都无法准确查询出含中文的数据,多少会有一些含有特殊字符的数据,比如 俄文:

ООО АВС-Электро 
ООО ИНТЕР 

不过,用正则工具测试,又匹配不上这些特殊字符。
正则在线测试:https://www.sojson.com/regex/

几种 SQL 写法参考

测试的几种 SQL 写法:

  1. 这种写法查询匹配到的数据目前是最准确的,不过还是含有俄文 或其它特殊字符。
SELECT name FROM user WHERE NOT (name REGEXP "[\u4e00-\u9fa5]");

奇怪的地方在于,对照上面中文正则范围,这个 SQL 语义应该是:查询 name 中不含中文的数据。结果这个 SQL 查询到的中文数据可能是最准确的。

参考前面 SQL 换种写法,在正则中取反,查询到的结果却完全不对,连普通的英文字符也都查询出来了。

SELECT name FROM user WHERE name REGEXP "[^\u4e00-\u9fa5]";

所以,真正的语义可能并不是我以为的那样。

  1. 这种写法才符合一般的正则匹配思路。
SELECT name FROM user WHERE name REGEXP "[一-龥]";

但查询到的数量是第1种方法的 9 倍,多出来了很多含特殊字符的数据,比如带变音符号的字母

CÔNG TY TNHH XE ĐẠP ĐIỆN ĐÀO KHÔI

这些字符同样,用正则工具测试也是匹配不上的。

  1. 这种查询通过判断字符长度来查询,与第2种方法中查询的数量一样
SELECT name FROM user WHERE length(name)!=char_length(name);

AI 可能也被问糊涂了,已经是建议在应用层面判断字符串中是否包含中文。当然,应用中正则应该会准确多了,实在没办法的话,就只好 MySQL 查询后,在代码中再加一层判断。

那么,还有其它方法可以用来在 MySQL 查询中文么,没想到会出现现在这种情况。

然后,目前第1种 SQL 可能是匹配准确率最高的,不过,不太理解,有没有热心大佬可以帮忙解释一下。

2 个赞

常规话题快问快答

我的猜想,不知道能不能参考,你用unicode的正则只是其中一部分,所以你的集合并不包含所有的中文字,自然取反的时候就还能查到其他中文字。
我问AI给我的unicode其实还包含其他范围的:
[\u4e00-\u9fa5\u3400-\u4DBF\u20000-\u2A6DF\u2A700-\u2B73F\u2B740-\u2B81F\u2B820-\u2CEAF\u2CEB0-\u2EBEF\u30000-\u3134F\uF900-\uFAFF\u2F800-\u2FA1F]
不妨试试我这个的答案行不行

刚试了下,查询效果跟我第一种 SQL 写法一样,我的困惑的点在于:

  1. REGEXP '[{exp}]' 查询不到中文(查询结果量太大,我只看了前 200 条是不含中文的),要用 NOT REGEXP '[{exp}]' 查询
  2. NOT REGEXP '[{exp}]'REGEXP '[^{exp}]' 查询结果也完全不是一回事

安装Php 管理吧。

包字符集及编码信息不全!