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

时间:2012-02-16 02:03:52

标签: mysql utf-8 character-encoding latin1

我即将承担将数据库从Latin1转换为UTF-8的繁琐且充满困难的任务。

此时我只想查看我在表格中存储的数据类型,因为这将决定我应该使用哪种方法来转换数据。

具体来说,我想检查一下Latin1列中是否有UTF-8字符,最好的方法是什么?如果只影响了几行,那么我可以手动修复它。

选项1.执行MySQL转储并使用Perl搜索UTF-8字符?

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

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

4 个答案:

答案 0 :(得分:45)

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

您可以做的是查找任何“高位ASCII”字符,因为它们是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正则表达式引擎似乎忽略\x80之类的内容而使得必须使用UNHEX()方法,因此异常复杂。

这会产生如下结果:

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

答案 1 :(得分:9)

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

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

答案 2 :(得分:3)

a script on github来帮助解决这类问题。

答案 3 :(得分:0)

我会为所有有效的UTF8序列创建数据库转储和grep。从哪里取出取决于你得到了什么。关于识别无效的UTF8,有多个问题;你基本上可以改变逻辑。

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