【问题标题】:How to clean data with special characters in MySQL如何在 MySQL 中清理带有特殊字符的数据
【发布时间】:2018-08-26 03:10:04
【问题描述】:

如何在 MySQL 中将类似 Réationl’Oreal 的数据分别清理为类似 R'actionL'Oreal 的数据?

【问题讨论】:

  • 谢谢@Madhur。这就是我一直在寻找的,但不知何故没有使用正确的词

标签: mysql utf-8 special-characters mojibake


【解决方案1】:

这看起来像是“双重编码”的一个例子。这是右手在说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 作为中间定义。 (请务必保持其他规格相同 - VARCHARNOT NULL 等)

对每个有问题的表中的每一列都这样做。

(在本次讨论中,我不区分 utf8mb4 和 utf8。大多数文本都非常满意;表情符号和一些中文需要 utf8mb4,而不仅仅是 utf8。)

来自评论

        CONVERT(UNHEX('C38EC2B2') USING utf8mb4) = 'β'  (Greek beta)
CONVERT(CONVERT(UNHEX('C38EC2B2') USING latin1) USING utf8mb4) = 'β'

我的结论:首先你有一些错误配置。然后你应用了一个或多个错误修复。你现在乱七八糟,我不敢帮你解开。也就是说,混乱不仅仅是“双重编码”。

如果可能,请重新开始,确保在添加更多数据之前正确存储了一些测试数据。如果数据不好,不要尝试修复数据;退后并重新开始。请参阅“Trouble...”中的“最佳括号”以正确设置。我会在附近帮助您解释您在表格中看到的十六进制是否正确。

【讨论】:

  • 感谢@Rick James。我已按照您的指示进行操作,可以说我的问题是双重编码。运行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)
  • @tomsawyer - UPDATE tbl SET words = CONVERT(BINARY(...));
  • @tomsawyer - 我需要考虑你现在是否有更糟糕的情况 - 我认为你必须在添加任何新行之前完全清理表架构和数据。如果您详细说明您采取的步骤和当前的 HEX,也许会有所帮助。请尝试使用复制粘贴;正如我发现的那样(React vs Redact 等),重新输入会导致错误复制。
  • 我花了数年时间才能够快速推断出 utf8 出现乱码的 5 种不同(并且有些常见)的方式。你的远远超出了这 5 个。我没有几年的时间来调试它。前 5 个来自(通常)在设置 utf8 时做错一件事。我担心做两件的事情顺序会导致5*5或5^5的情况。哎呀! (我添加到我的答案中。)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-10-29
  • 2022-10-07
  • 1970-01-01
  • 2018-04-07
  • 2019-07-12
  • 1970-01-01
  • 2016-03-07
相关资源
最近更新 更多