解决MySQL报错:ERROR 1366 (HY000): Incorrect string value…[超详细分析]

解决MySQL报错:ERROR 1366 (HY000): Incorrect string value…[超详细分析]_荒原之梦

报错详情

使用的命令和遇到的报错如下:

mysql> insert TestTable(ID, Name, Gender, HireDate) values('2021001', '赵凯峰', '男', '2021-01-01');
ERROR 1366 (HY000): Incorrect string value: '\xE8\xB5\xB5\xE5\x87\xAF...' for column 'Name' at row 1

注:

  1. 本文中使用数据库名称为 TestBase;
  2. 本文中使用的数据表名称为 TestTableTestTable2.

报错分析

“Incorrect string value” 的意思就是“字符串值错误”,一般情况下,这样的报错意味着数据库中的编码存在问题。

可以使用如下命令查看数据库当前的编码方式:

show create database TestBase;

回显结果如下:

+----------+-------------------------------------------------------------------+
| Database | Create Database                                                   |
+----------+-------------------------------------------------------------------+
| TestBase   | CREATE DATABASE `TestBase` /*!40100 DEFAULT CHARACTER SET latin1 */ |
+----------+-------------------------------------------------------------------+
1 row in set (0.00 sec)

DEFAULT CHARACTER SET latin1 可知,数据库当前默认的编码格式为 latin1. 从名称可以猜测,latin1 编码是一种主要用于拉丁(Latin)语系文字和符号的编码方案,事实上,latin1 码除了向下兼容专用于拉丁语系字母和符号的 ASCII 码之外,还能表示西欧语言、希腊语、泰语、阿拉伯语和希伯来语中出现的字母和符号——也就是说,latin1 码是无法解码中文字符的,如果让 MySQL 以默认的 latin1 编码格式处理包含中文的内容就会导致上述报错。

解决方案一

修改已存在的数据库编码格式为 UTF-8:

alter database TestBase character set utf8;

解决方案二

在创建数据库的时候指定编码格式为 UTF-8:

create database TestBase character set utf8;

解决方案三

在 MySQL 中,我们可以为数据库、数据表和数据列分别设置编码格式,而且,在指定了编码格式的情况下,数据列的编码格式优先于数据表,数据表的编码格式优先于数据列;在没有指定编码格式的情况下,数据列继承数据表的编码格式,数据表继承数据库的编码格式——但是继承是以时序为前提的,例如,数据表继承的是在创建该表前数据库的编码格式,在一个数据表已经存在的情况下,修改该数据表所在数据库的编码格式并不会导致该数据表原有编码格式的改变。

比如,我们先创建一个使用默认的 latin1 编码格式的数据库:

mysql> create database TestBase;
Query OK, 1 row affected (0.00 sec)

mysql> show create database TestBase;
+----------+---------------------------------------------------------------------+
| Database | Create Database                                                     |
+----------+---------------------------------------------------------------------+
| TestBase | CREATE DATABASE `TestBase` /*!40100 DEFAULT CHARACTER SET latin1 */ |
+----------+---------------------------------------------------------------------+
1 row in set (0.00 sec)

接着,在不指定编码格式的情况下创建一个包含 Name 数据列的数据表(由前述可知,此时该数据表的编码格式为 latin1):

mysql> use TestBase;
Database changed
mysql> create table TestTable1
    -> (
    -> Name varchar(20)
    -> );
Query OK, 0 rows affected (0.07 sec)

然后,尝试在 Name 数据列中插入包含中文的数据,发现会报错,插入全英文的数据就不会报错:

mysql> insert TestTable1 (Name) values ('荒原之梦网');
ERROR 1366 (HY000): Incorrect string value: '\xE8\x8D\x92\xE5\x8E\x9F...' for column 'Name' at row 1

mysql> insert TestTable1 (Name) values ('zhaokaifeng.com');
Query OK, 1 row affected (0.01 sec)

同样还是在 TestTable1 这个表里面,我们新增加一个名为 NickName 的数据列,同时使用 character set utf8 设定该数据列使用 UTF-8 编码:

mysql> alter table TestTable1 add column NickName varchar(20) character set utf8 after Name;
Query OK, 0 rows affected (0.04 sec)
Records: 0  Duplicates: 0  Warnings: 0

之后,在 TestTable1 表下面的 NickName 数据列下插入包含中文的数据,显示可以正常插入:

mysql> insert TestTable1 (NickName) values ('小原和小梦');
Query OK, 1 row affected (0.03 sec)

接着,在 TestTable1 表下面的 Name 数据列下插入包含中文的数据,显示不可以正常插入,这说明我们刚才的编码设定只对 NickName 数据列有效,即便 NickName 数据列和 Nmae 数据列都在同一个数据表里面也互不干扰:

mysql> insert TestTable1 (Name) values ('小原和小梦');
ERROR 1366 (HY000): Incorrect string value: '\xE5\xB0\x8F\xE5\x8E\x9F...' for column 'Name' at row 1

我们还可以在创建数据表的时候为其指定默认的编码格式,例如,我们在编码格式为 latin1TestBase 的数据库中创建一个名为 TestTable2 的数据表,该表的默认编码设定为 UTF-8. 同时,在 TestTable2 数据表中创建两个数据列,分别是不指定编码的 Name2 数据列和指定编码格式为 latin1NickName 数据列:

l> create table TestTable2
    -> (
    -> Name2 varchar(20),
    -> NickName2 varchar(20) character set latin1
    -> )default charset=utf8;
Query OK, 0 rows affected (0.02 sec)

之后,我们在 Name2 数据列中插入中文,发现可以正常插入,说明未指定编码格式的数据列继承了为数据表指定的 UTF-8 编码格式:

mysql> insert TestTable2 (Name2) values ('荒原之梦网');
Query OK, 1 row affected (0.00 sec)

而当我们在 NickName 数据列中尝试插入中文时,发现不可以正常插入,这说明数据列指定的编码格式的优先级高于数据表的编码格式:

mysql> insert TestTable2 (NickName2) values ('小原和小梦');
ERROR 1366 (HY000): Incorrect string value: '\xE5\xB0\x8F\xE5\x8E\x9F...' for column 'NickName2' at row 1

最后,我们再来查看一下数据库 TestBase 的编码格式,发现其编码格式仍然是 latin1, 这说明,我们对数据表和数据列编码格式的设定并没有影响到数据库的编码格式:

mysql> show create database TestBase;
+----------+---------------------------------------------------------------------+
| Database | Create Database                                                     |
+----------+---------------------------------------------------------------------+
| TestBase | CREATE DATABASE `TestBase` /*!40100 DEFAULT CHARACTER SET latin1 */ |
+----------+---------------------------------------------------------------------+
1 row in set (0.00 sec)

发表回复


荒原之梦网全部内容均为原创,提供了涵盖考研数学基础知识、考研数学真题、考研数学练习题和计算机科学等方面,大量精心研发的学习资源。

豫 ICP 备 17023611 号-1 | 公网安备 - 荒原之梦 豫公网安备 41142502000132 号 | SiteMap
Copyright © 2017-2024 ZhaoKaifeng.com 版权所有 All Rights Reserved.

Copyright © 2024   zhaokaifeng.com   All Rights Reserved.
豫ICP备17023611号-1
 豫公网安备41142502000132号

荒原之梦 自豪地采用WordPress