为什么在MySQL 5.7.22中utf8mb4列拒绝4字节字符?

时间:2018-07-05 18:21:57

标签: mysql utf-8 utf8mb4

我正在尝试将所有4字节字符的字符串保存到MySQL utf8mb4列中。

UPDATE `uga_libsteam`.`group_history` SET `source_name`='' WHERE `group_id`='103582791430024497' and`history_id`='1655';

字符如下。

但是,当我运行此查询时,我收到此错误。

Executing:
UPDATE `uga_libsteam`.`group_history` SET `source_name`='' WHERE `group_id`='103582791430024497' and`history_id`='1655';

Operation failed: There was an error while applying the SQL script to the database.
ERROR 1366: 1366: Incorrect string value: '\xF0\x9D\x93\x94\xF0\x9D...' for column 'source_name' at row 1
SQL Statement:
UPDATE `uga_libsteam`.`group_history` SET `source_name`='' WHERE `group_id`='103582791430024497' and`history_id`='1655'

这是我的架构。标题已弃用,最终我将其删除。以前,source_name和target_name都是utf8 / utf8_unicode_ci,但我昨晚能够解决该问题。

CREATE TABLE `group_history` (
  `group_id` bigint(20) unsigned NOT NULL,
  `history_id` bigint(20) unsigned NOT NULL,
  `type_id` tinyint(2) DEFAULT NULL,
  `title` varchar(32) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL,
  `display_date` datetime DEFAULT NULL,
  `year_offset` tinyint(2) unsigned DEFAULT NULL,
  `month` tinyint(2) unsigned DEFAULT NULL,
  `day` tinyint(2) unsigned DEFAULT NULL,
  `time` time DEFAULT NULL,
  `source_name` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  `source_steam_id` bigint(20) DEFAULT NULL,
  `target_name` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  `target_steam_id` bigint(20) DEFAULT NULL,
  PRIMARY KEY (`group_id`,`history_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

为什么数据库拒绝应该合法输入的字符?我是否必须切换到UTF-32才能工作?

2 个答案:

答案 0 :(得分:1)

  

以前,source_name和target_name都是utf8 / utf8_unicode_ci,但我昨晚能够解决该问题。

我猜您尝试通过更改表的默认字符集来修复字符集。

ALTER TABLE group_history DEFAULT CHARSET utf8mb4;

这不会更改表现有列的字符集,它只会更改表的默认字符集,仅当您随后添加新列时才使用。现有列仍使用旧字符集utf8进行编码。

要转换现有的列,必须使用:

ALTER TABLE group_history CONVERT TO CHARACTER SET utf8mb4;

这将使用新字符集重写所有现有的字符串列,并随后允许您插入4字节字符值。

答案 1 :(得分:0)

Thanks to this answerI had to run this,然后才能插入数据库...

SET NAMES utf8mb4 COLLATE utf8mb4_unicode_ci;

好消息是我现在可以在数据库中插入数据了,坏消息是我正在为PHP应用程序编写代码,PDO无法正常工作并且正在保存吗?到数据库。

编辑:Thanks to this question,我也找到了解决PHP问题的方法。这是我的代码之前的样子:

    $dsn = "mysql:host=$this->hostname;port=$this->port;dbname=$this->database;charset=utf8mb4";
    try {
        $this->pdo = new \PDO($dsn, $this->username, $this->password, array(\PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION));
        $this->pdo->exec('SET NAMES utf8mb4 COLLATE utf8mb4_unicode_ci;');
    } catch (\PDOException $e) {
        die($e->getMessage());
    }

这就是我必须将其更改为:

    $dsn = "mysql:host=$this->hostname;port=$this->port;dbname=$this->database;charset=utf8mb4";
    try {
        $this->pdo = new \PDO($dsn, $this->username, $this->password, array(\PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION, \PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8mb4 COLLATE utf8mb4_unicode_ci'));
    } catch (\PDOException $e) {
        die($e->getMessage());
    }