MySQL - 更新时无效的utf8mb4字符串

问题描述 投票:2回答:1

我的问题几乎与这里发现的问题完全相同

MySQL - 1300 - Invalid utf8 character string on update

没有提出解决方案,这个人的帮助(创建临时表)似乎没有帮助。这是我正在使用的select语句:

SELECT
    CONVERT(line_1 USING utf8mb4),
    CONVERT(line_1 USING latin1),
    HEX(line_1)
FROM address
WHERE ((CAST(CONVERT(line_1 USING latin1) AS CHAR)) <> (CAST(line_1 AS CHAR)))
    AND CONVERT(line_1 USING utf8mb4) IS NULL;
+-------------------------------+------------------------------+----------------------------------------------------+
| CONVERT(line_1 USING utf8mb4) | CONVERT(line_1 USING latin1) | hex(line_1)                                        |
+-------------------------------+------------------------------+----------------------------------------------------+
| NULL                          | Högbergsgatan 97             | 48F6676265726773676174616E203937                   |
| NULL                          | Zücherstrasse 161            | 5AFC636865727374726173736520313631                 |
| NULL                          | 2275, Rue de l'Université    | 323237352C20527565206465206C27556E69766572736974E9 |
| NULL                          | Högbergsgatan 97             | 48F6676265726773676174616E203937                   |
+-------------------------------+------------------------------+----------------------------------------------------+

当我尝试运行以下更新命令时,我得到:

UPDATE address
SET line_1 = CONVERT(CAST(CONVERT(line_1 USING latin1) AS CHAR) USING utf8mb4)
WHERE (CAST(CONVERT(line_1 USING latin1) AS CHAR) <> CAST(line_1 AS CHAR))
    AND CONVERT(line_1 USING utf8mb4) IS NULL;
ERROR 1300 (HY000): Invalid utf8mb4 character string: 'F66762'

我尝试以下列方式设置行,都产生相同的错误:

SET line_1 = CAST(CONVERT(line_1 USING latin1) AS CHAR)
SET line_1 = CONVERT(line_1 USING latin1)

我还看了http://jonisalonen.com/2012/fixing-doubly-utf-8-encoded-text-in-mysql/,看看它是否是一个双重编码问题,但这些都没有奏效,我一直得到相同的字符串错误。

另外,为了帮助转换步骤,我查看了https://mathiasbynens.be/notes/mysql-utf8mb4,但utf8mb4和utf8导致完全相同的问题。 (起初我认为这是一件事,所以我切换到utf8mb4,当我仍然遇到同样的问题时,我知道有更深层次的问题)

正如你所看到的,正在发生一些奇怪的事情。查看我的show create address表,我可以验证charset是否设置正确:

SHOW CREATE TABLE address;
| address | CREATE TABLE `address` (
  `addressid` bigint(20) NOT NULL AUTO_INCREMENT,
  `addressuuid` char(32) COLLATE utf8mb4_unicode_ci NOT NULL,
  `line_1` blob,
  PRIMARY KEY (`addressid`)
) ENGINE=InnoDB AUTO_INCREMENT=48970 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='All potential addresses' |

此外,您可以在我的实例中看到我的字符变量是正确的:

mysql> show variables like 'char%';
+--------------------------+----------------------------+
| Variable_name            | Value                      |
+--------------------------+----------------------------+
| character_set_client     | utf8mb4                    |
| character_set_connection | utf8mb4                    |
| character_set_database   | utf8                       |
| character_set_filesystem | binary                     |
| character_set_results    | utf8mb4                    |
| character_set_server     | utf8mb4                    |
| character_set_system     | utf8                       |
| character_sets_dir       | /usr/share/mysql/charsets/ |
+--------------------------+----------------------------+
8 rows in set (0.00 sec)

我怎么到这里了

因此,提供有关该问题的一些背景信息可能是有益的,以防万一它在背景中导致问题。

我有一个数据库,最初设置为latin1编码所有。然后我运行以下代码:

SET NAMES 'latin1';

/* We must change things to blob and then back again */
ALTER TABLE `address` CHANGE line_1 line_1 BLOB;
ALTER TABLE `address` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE `address` CHANGE line_1 line_1 VARCHAR(64);

切换到blob然后返回varchar的原因是正常的建议过程。 (www.percona.com/blog/2013/10/16/utf8-data-on-latin1-tables-converting-to-utf8-without-downtime-or-double-encoding/)

如果有帮助,请告诉我,如果有更多信息可以提供。我正在使用MySQL 5.6所以理论上它应该更好地处理事情,但谁知道呢。由于只有4行我可以手动更新每一行,但理论上存在更大的潜在问题,因为我确实有更多的列需要通过,所以确保我有一个功能方法是很好的处理这些情况,以防万一我得到了很多行。

character-encoding mysql-5.6 utf8mb4
1个回答
0
投票

由于line_1是一个blob而不是文本字段,因此MySQL无法控制其中的“字符”,并且不关心它是否是非文本信息(例如JPG)。在您给出的示例中,您在该字段中有latin1文本(例如,ö的十六进制F6)。因此,CONVERT(line_1 USING latin1)工作得很好。

我不明白你的目标。您是否尝试将BLOB读作TEXT?如果是这样,并且如果所有非ascii字符都被编码为latin1,那么CONVERT就是答案。

如果你的目标是别的,那么让我们从那里接近它。

它不是“双重编码”,所以它们都不会起作用。

ALTER TABLE address CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

做一个SHOW CREATE TABLE address并检查line_1的CHARACTER SET。

© www.soinside.com 2019 - 2024. All rights reserved.