如何检测Latin1编码列中的UTF-8字符 – MySQL

我将要完成将数据库从Latin1转换为UTF-8的繁琐和棘手的任务。

在这一点上,我只是想检查我的表中存储了哪些数据,因为这将决定我应该使用什么方法来转换数据。

具体而言,我想检查在Latin1列中是否有UTF-8字符,那么执行此操作的最佳方法是什么? 如果只有几行受到影响,那么我可以手动修复这个问题。

选项1.执行MySQL转储并使用Perl来searchUTF-8字符?

选项2.使用MySQL CHAR_LENGTH查找具有多字节字符的行? SELECT name FROM clients WHERE LENGTH(name) != CHAR_LENGTH(name); 这够了吗?

目前,我已将我的Mysql客户端编码切换为UTF-8。

像时区一样,字符编码是问题的常见来源。

你可以做的是查找任何“高-HASCII”字符,因为它们是LATIN1重音字符或符号,或者是第一个UTF-8多字节字符。 除非你欺骗一点点,否则说出这个区别并不容易。

要弄清楚什么编码是正确的,你只需SELECT两个不同的版本,并进行可视化比较。 这是一个例子:

 SELECT CONVERT(CONVERT(name USING BINARY) USING latin1) AS latin1, CONVERT(CONVERT(name USING BINARY) USING utf8) AS utf8 FROM users WHERE CONVERT(name USING BINARY) RLIKE CONCAT('[', UNHEX('80'), '-', UNHEX('FF'), ']') 

这是非常复杂的,因为MySQL的正则expression式引擎似乎忽略像\x80东西,使有必要使用UNHEX()方法。

这产生这样的结果:

 latin1 utf8 ---------------------------------------- Björn Björn 

由于您的问题还不完全清楚,我们假设一些情况:

  1. 迄今为止错误的连接:您使用latin1编码错误地连接到了数据库,但是在数据库中存储了UTF-8数据(在这种情况下,列的编码是不相关的)。 这是我在这里描述的情况。 在这种情况下,很容易修复: 通过latin1连接将数据库内容转储到文件。 这会将错误地存储的数据转换成错误地正确存储的UTF-8,这是迄今为止工作的方式(请阅读上述关于血腥细节的文章)。 然后,您可以通过正确设置的utf8连接将数据重新导入到数据库中,并将其按原样存储。
  2. 迄今为止错误的列编码:通过utf8连接将UTF-8数据插入到latin1列中。 在那种情况下,忘记它,数据就消失了。 任何非latin1字符应该被replace为?
  3. 到目前为止,一切都很好,从此以后又增加了对UTF-8的支持:你已经将Latin-1的数据正确地存储在一个latin1列中,通过latin1连接插入,但是要扩展到允许UTF-8的数据。 在这种情况下,只需将列编码更改为utf8。 MySQL会为你转换现有的数据。 然后,只要确保在插入UTF-8数据时将数据库连接设置为utf8。

在github上有一个脚本来帮助这种事情。

我会为所有有效的UTF8序列创build数据库和grep的转储。 从哪里拿到它取决于你得到什么。 关于识别无效的UTF8有很多问题。 你基本上可以逆转逻辑。

编辑 :基本上,任何由7位ASCII组成的字段是安全的,任何包含无效UTF-8序列的字段都可以假定为Latin-1。 剩下的数据应该被检查 – 如果你幸运的话,less数几个明显的replace将会解决绝大多数(用Latin-1replaceö等等)。