【问题标题】:Invalid utf8 character string. Converting "latin1_german1_ci" column entirely into UTF8无效的 utf8 字符串。将“latin1_german1_ci”列完全转换为 UTF8
【发布时间】:2020-01-09 11:30:39
【问题描述】:

我有一个表,其中有一列的数据似乎不是 UTF8。我想将该列转换为 UTF8。

我发现了这个很棒的教程:https://coderwall.com/p/gjyuwg/mysql-convert-encoding-to-utf8-without-garbled-data

但是,这些解决方案都没有真正奏效。

当我这样做时

UPDATE vbpmtext 
SET message = @txt 
WHERE char_length(message) =  LENGTH(@txt := CONVERT(BINARY CONVERT(message USING latin1) USING utf8));

我遇到很多这样的错误:

Invalid utf8 character string: 'FC6265'

使用不同的“字符串”(FC6265 只是一个例子)。

有什么办法可以挽救这些数据吗?

我们所说的列自然是用latin1_german1_ci的排序规则格式化的。

【问题讨论】:

  • 对不起。我似乎无法登录该 coderwall 链接,否则我会给他们一些想法。问题并不像他们说的那么简单。此外,提供多种解决方案,但不说何时适用!

标签: mysql utf-8 collation iso-8859-1 character-set


【解决方案1】:

解释为 latin1,FC6265übe。 (同样适用于 cp1250、cp1256、cp1257、dec8、latin2、latin5、latin7。)

@txt 是 3 个字符的字符串 übe?还是6个字符的字符串FC6265

mysql> SET @in := UNHEX('FC6265');
mysql> SELECT HEX(@in);
+----------+
| HEX(@in) |
+----------+
| FC6265   |
+----------+
mysql> SELECT HEX( CONVERT(@in USING latin1) );
+----------------------------------+
| HEX( CONVERT(@in USING latin1) ) |
+----------------------------------+
| FC6265                           |
+----------------------------------+
mysql> SELECT HEX( BINARY(CONVERT(@in USING latin1)) );
+------------------------------------------+
| HEX( BINARY(CONVERT(@in USING latin1)) ) |
+------------------------------------------+
| FC6265                                   |
+------------------------------------------+
mysql> SELECT HEX( CONVERT(BINARY CONVERT(@in USING latin1) USING utf8) );
+-------------------------------------------------------------+
| HEX( CONVERT(BINARY CONVERT(@in USING latin1) USING utf8) ) |
+-------------------------------------------------------------+
|                                                             |
+-------------------------------------------------------------+
1 row in set, 1 warning (0.00 sec)
mysql> SHOW WARNINGS;
+---------+------+-----------------------------------------+
| Level   | Code | Message                                 |
+---------+------+-----------------------------------------+
| Warning | 1300 | Invalid utf8 character string: 'FC6265' |
+---------+------+-----------------------------------------+

使用BINARY() 消除了对字符串当前编码为的任何假设。所以它采用最简单的方法并假设字符串已经是utf8

这可能是最短的方法:

mysql> SELECT CONVERT(CONVERT(@in USING latin1) USING utf8);
+-----------------------------------------------+
| CONVERT(CONVERT(@in USING latin1) USING utf8) |
+-----------------------------------------------+
| übe                                           |
+-----------------------------------------------+

但是...该列的字符集是什么?如果它是 latin1,那么您将变得更糟。 不要在没有进一步测试的情况下进行任何更改。 Here 有几种情况,每种情况都有修复。在确定您是否遇到这种情况之前,不要急于采用一种解决方案;你可能会让事情变得更糟。另见Trouble with UTF-8 characters; what I see is not what I stored

示例

mysql> CREATE TABLE ube ( c VARCHAR(8) CHARSET latin1 COLLATE latin1_german1_ci );

mysql> INSERT INTO ube (c) VALUES (UNHEX('FC6265'));

mysql> SELECT HEX(c) FROM ube;
+--------+
| HEX(c) |
+--------+
| FC6265 |  -- Note the latin1 encoding
+--------+

mysql> ALTER TABLE ube CONVERT TO CHARACTER SET utf8mb4;
Query OK, 1 row affected (0.04 sec)
Records: 1  Duplicates: 0  Warnings: 0   -- Note: no errors

mysql> SELECT HEX(c) FROM ube;
+----------+
| HEX(c)   |
+----------+
| C3BC6265 |   -- Now utf8mb4 encoding
+----------+

【讨论】:

  • 非常感谢!我的桌子是:DEFAULT CHARSET=latin1 COLLATE=latin1_german1_ci。这不起作用:ALTER TABLE tbl CONVERT TO CHARACTER SET utf8mb4;.
  • Then to convert the column without changing the bytes: 下的 2-step alter 也不会t work. In both cases I get this error: Malformed UTF-8 字符,可能编码不正确。`
  • @Hillcow - 第一个 ALTER 对我有用。请参阅我的答案中的示例。你对SELECT HEX(col) 有什么看法?
  • 必须在执行转换之前验证您的情况。
【解决方案2】:

好吧,这是我的错。并不是数据本身已损坏,而是我在数据上使用了 php substr 方法,该方法在不幸的地方剪切了数据。在这里找到了解决方案:php substr() function with utf-8 leaves � marks at the end

$var = "Бензин Офиси А.С. также производит все типы жира и смазок и их побочных        продуктов в его смесительных установках нефти машинного масла в Деринце, Измите, Алиага и Измире. У Компании есть 3 885 станций технического обслуживания, включая сжиженный газ (ЛПГ) станции под фирменным знаком Петрогаз, приблизительно 5 000 дилеров, двух смазочных смесительных установок, 12 терминалов, и 26 единиц поставки аэропорта.";

$foo = mb_substr($var,0,142, "utf-8");

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-01-29
    • 2010-12-04
    • 1970-01-01
    • 2012-07-17
    • 2020-10-11
    • 2012-03-13
    • 2017-02-12
    • 2012-02-01
    相关资源
    最近更新 更多