如何修复双编码 UTF8 字符(在 utf-8 表中)
Posted
技术标签:
【中文标题】如何修复双编码 UTF8 字符(在 utf-8 表中)【英文标题】:How to fix double-encoded UTF8 characters (in an utf-8 table) 【发布时间】:2012-07-11 07:17:17 【问题描述】:之前的LOAD DATA INFILE
是在假设CSV 文件是latin1
编码的情况下运行的。在此导入期间,多字节字符被解释为两个单个字符,然后使用 utf-8(再次)进行编码。
这种双重编码创建了像ñ
这样的异常,而不是ñ
。
如何更正这些字符串?
【问题讨论】:
@Esailija 这不是 mysql 函数。无需将 php 等工具引入图片即可解决。 (这个问题是为了自我回答而创建的,但如果出现更好的解决方案,我会接受它而不是我的)。 很高兴知道,将此标记为收藏,以便我需要时可以找到它 【参考方案1】:以下 MySQL 函数将在双重编码后返回正确的 utf8 字符串:
CONVERT(CAST(CONVERT(field USING latin1) AS BINARY) USING utf8)
它可以与UPDATE
语句一起使用来更正字段:
UPDATE tablename SET
field = CONVERT(CAST(CONVERT(field USING latin1) AS BINARY) USING utf8);
【讨论】:
我大部分时间都在工作,但发现一个不起作用的序列:字母ě
是 C49B
但在我的数据库中显示为 c384c29b
和 SELECT HEX(CONVERT(CAST(0xc384c29b AS CHAR) USING latin1))
得到了无效的 UTF-8字节序列C43F
这意味着你最外层的CONVERT
不起作用。 UTF-8 字节 c29b
应该是 Unicode 9B
但 MySQL 将其设置为 3F
(?
) 大概是因为这是 latin1 中的控制字符。不过 Perl 的 utf8::decode 可以使用它。
我不能不说我很高兴我找到了这个解决方案:)
太棒了。这似乎有效。现在我的挑战是弄清楚是只有 some 记录有这个编码错误,还是全部都有。我可能只需要搜索字符不正确的记录。
哇...我正在尝试通过 PHP 完成此任务,但您节省了我的时间。 100% 在我的数据库中工作。
谢谢!每个人都应该看到Eric’s enhancement,它可以防止由于null
结果而导致的数据丢失(如果特定列已经是非ASCII utf8
,即不是latin1
,则可以得到)。【参考方案2】:
上面的答案适用于我的一些数据,但运行后导致很多 NULL 列。我的想法是,如果转换不成功,它会返回 null。为了避免这种情况,我加了一张小支票。
UPDATE
tbl
SET
col =
CASE
WHEN CONVERT(CAST(CONVERT(col USING latin1) AS BINARY) USING utf8) IS NULL THEN col
ELSE CONVERT(CAST(CONVERT(col USING latin1) AS BINARY) USING utf8)
END
【讨论】:
救了我的命!完美的!!谢谢! 防止数据丢失的一个非常重要的补充,谢谢!您可以通过将CASE WHEN converted IS NULL THEN original ELSE converted END
替换为IF(converted IS NULL, original, converted)
甚至IFNULL(converted, original)
来进一步简化此操作。【参考方案3】:
我也遇到这个问题,这里是Oracle的解决方案:
update tablename t set t.colname = convert(t.colname, 'WE8ISO8859P1', 'UTF8') where t.colname like '%Ã%'
还有一个用于 Java 的:
public static String fixDoubleEncoded(String text)
final Pattern pattern = Pattern.compile("^.*Ã[^0-9a-zA-Z\\ \t].*$");
try
while (pattern.matcher(text).matches())
text = new String(text.getBytes("iso-8859-1"), "utf-8");
catch (UnsupportedEncodingException e)
e.printStackTrace();
return text;
【讨论】:
【参考方案4】:使用“utf8mb4”而不是“utf8”非常重要,因为mysql会在一个无法识别的字符之后删除所有数据。所以更安全的方法是;
UPDATE tablename SET
field = CONVERT(CAST(CONVERT(field USING latin1) AS BINARY) USING utf8mb4);
小心这个。
【讨论】:
如果你的排序规则不是 utf8mb4_unicode_ci ,首先改变这个:ALTER TABLEtablename
modify fieldname
type CHARACTER SET utf8mb4
COLLATE utf8mb4_unicode_ci
以上是关于如何修复双编码 UTF8 字符(在 utf-8 表中)的主要内容,如果未能解决你的问题,请参考以下文章