【发布时间】:2018-08-26 03:10:04
【问题描述】:
如何在 MySQL 中将类似 Réation、l’Oreal 的数据分别清理为类似 R'action 和 L'Oreal 的数据?
【问题讨论】:
-
谢谢@Madhur。这就是我一直在寻找的,但不知何故没有使用正确的词
标签: mysql utf-8 special-characters mojibake
如何在 MySQL 中将类似 Réation、l’Oreal 的数据分别清理为类似 R'action 和 L'Oreal 的数据?
【问题讨论】:
标签: mysql utf-8 special-characters mojibake
这看起来像是“双重编码”的一个例子。这是右手在说utf8,但左手在听latin1的地方。参见Trouble with UTF-8 characters; what I see is not what I stored 和参见http://mysql.rjweb.org/doc.php/charcoll#fixes_for_various_cases。
Réation -> Réation 撤销双重编码后。
但是你说R'action——我想知道你是把é写成e'还是'e??
我还会假设您的意思是L’Oreal?? (注意“右单引号”而不是“撇号”。)
首先,我们需要验证它实际上是一个普通的双重编码。
SELECT col, HEX(col) FROM ... WHERE ...
应该给你这个Réation的十六进制:
52 E9 6174696F6E -- latin1 encoding
52 C3A9 6174696F6E -- utf8 encoding
52 C383 C2A9 6174696F6E -- double encoding
(忽略间距。)
如果你得到了其中的第三个,请继续我的回答。 如果你得到任何东西,停止! -- 问题比我想象的要复杂。
现在,看看双编码修复是否会修复它(修复之前):
SELECT col, CONVERT(BINARY(CONVERT(CONVERT(
BINARY(CONVERT(col USING latin1)) USING utf8mb4)
USING latin1)) USING utf8mb4)
FROM tbl;
您需要防止它发生并修复数据。 以下某些情况是不可逆的;在表的副本上测试它!
您的情况是:CHARACTER SET latin1,但其中包含 utf8/utf8mb4 字节;修复字符集时不要管字节:
首先,假设您有 tbl.col 的声明:
col VARCHAR(111) CHARACTER SET latin1 NOT NULL
然后在不改变字节的情况下转换列:
ALTER TABLE tbl MODIFY COLUMN col VARBINARY(111) NOT NULL;
ALTER TABLE tbl MODIFY COLUMN col VARCHAR(111) CHARACTER SET utf8mb4 NOT NULL;
注意:如果您以TEXT 开头,请使用BLOB 作为中间定义。 (请务必保持其他规格相同 - VARCHAR、NOT NULL 等)
对每个有问题的表中的每一列都这样做。
(在本次讨论中,我不区分 utf8mb4 和 utf8。大多数文本都非常满意;表情符号和一些中文需要 utf8mb4,而不仅仅是 utf8。)
来自评论
CONVERT(UNHEX('C38EC2B2') USING utf8mb4) = 'β' (Greek beta)
CONVERT(CONVERT(UNHEX('C38EC2B2') USING latin1) USING utf8mb4) = 'β'
我的结论:首先你有一些错误配置。然后你应用了一个或多个错误修复。你现在乱七八糟,我不敢帮你解开。也就是说,混乱不仅仅是“双重编码”。
如果可能,请重新开始,确保在添加更多数据之前正确存储了一些测试数据。如果数据不好,不要尝试修复数据;退后并重新开始。请参阅“Trouble...”中的“最佳括号”以正确设置。我会在附近帮助您解释您在表格中看到的十六进制是否正确。
【讨论】:
SELECT col, HEX(col) FROM ... 后我得到了52C383C2A964616374696F6E3A。双编码修复解决了这个问题。但是,我迷失了如何修复表中已有的数据。我按照建议更改了相关表格,但这仅在插入新的双编码文本时才解决问题。我的问题是用双编码文本更新表格,以便表格中出现像这样 Rédaction 的文本更改为 @987654345 @.
update test set words = select words,convert(binary(convert(convert( binary(convert(words using latin1)) using utf8mb4) using latin1)) using utf8mb4) from test; 进行更新,但我得到了ERROR 1064 (42000)
UPDATE tbl SET words = CONVERT(BINARY(...));