MySQL 插入中文报错 ERROR 1366 (HY000): Incorrect string value 的完整解决记录
一、问题现象
今天在 MySQL 中新建了一个数据库和表,准备插入一些测试数据。当插入英文字符时一切正常,但插入中文时却报错了。
1. 复现步骤
sql
-- 创建数据库
mysql> create database aa;
Query OK, 1 row affected (0.00 sec)
-- 切换数据库
mysql> use aa;
Database changed
-- 创建测试表
mysql> create table bb(name varchar(255),age int);
Query OK, 0 rows affected (0.01 sec)
-- 尝试插入中文数据(报错!)
mysql> insert into bb values('张三',23);
ERROR 1366 (HY000): Incorrect string value: '\xE5\xBC\xA0\xE4\xB8\x89' for column 'name' at row 1
-- 插入英文数据(正常)
mysql> insert into bb values("zhangsan",23);
Query OK, 1 row affected (0.00 sec)
2. 错误信息解读
- 错误码 :
ERROR 1366 (HY000) - 错误提示 :
Incorrect string value: '\xE5\xBC\xA0\xE4\xB8\x89' for column 'name' at row 1 - 含义 :第 1 行的
name列的字符串值不正确,无法识别中文编码。
二、问题排查
1. 查看表结构
sql
mysql> show create table bb;
输出结果:
sql
+-------+-----------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table |
+-------+-----------------------------------------------------------------------------------------------------------------------------+
| bb | CREATE TABLE `bb` (
`name` varchar(255) DEFAULT NULL,
`age` int(11) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1 |
+-------+-----------------------------------------------------------------------------------------------------------------------------+
发现问题 :表的默认字符集是 latin1,而不是 utf8。latin1 是单字节编码,无法存储中文。
三、第一次尝试:修改表的默认字符集
参考网上的方法,先尝试修改表的默认字符集:
sql
mysql> alter table bb default character set utf8;
Query OK, 0 rows affected (0.00 sec)
Records: 0 Duplicates: 0 Warnings: 0
修改后再次查看表结构:
sql
mysql> show create table bb;
输出结果:
sql
+-------+------------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table |
+-------+------------------------------------------------------------------------------------------------------------------------------------------------+
| bb | CREATE TABLE `bb` (
`name` varchar(255) CHARACTER SET latin1 DEFAULT NULL,
`age` int(11) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8 |
+-------+------------------------------------------------------------------------------------------------------------------------------------------------+
注意 :虽然表的默认字符集已经变成了 utf8,但 name 列的字符集仍然是 latin1!
再次插入中文测试:
sql
mysql> insert into bb values("张三",23);
ERROR 1366 (HY000): Incorrect string value: '\xE5\xBC\xA0\xE4\xB8\x89' for column 'name' at row 1
结论 :只修改表的默认字符集是不够的,列的字符集没有随之改变。
四、第二次尝试:修改列的字符集
需要单独修改 name 列的字符集为 utf8:
sql
mysql> alter table bb change name name varchar(20) character set utf8;
Query OK, 1 row affected (0.04 sec)
Records: 0 Duplicates: 0 Warnings: 0
再次插入中文:
sql
mysql> insert into bb values("张三",23);
Query OK, 1 row affected (0.00 sec)
成功!
五、验证结果
sql
mysql> select * from bb;
+----------+------+
| name | age |
+----------+------+
| zhangsan | 23 |
| 张三 | 23 |
+----------+------+
2 rows in set (0.00 sec)
中文数据已经成功插入并正常显示。
六、问题总结
核心原因
MySQL 中,表级别 的默认字符集和列级别的字符集是分开的:
| 层级 | 作用范围 | 说明 |
|---|---|---|
| 数据库级别 | 整个数据库 | 影响新建表的默认字符集 |
| 表级别 | 整张表 | 影响新建列的默认字符集 |
| 列级别 | 单个字段 | 决定该字段实际存储的编码 |
当使用 alter table ... default character set utf8 时,只修改了表级别的默认字符集,已经存在的列的字符集不会自动改变。
正确解决方法
方法一:修改已有列的字符集(适用于已有数据的表)
sql
-- 修改指定列的字符集
alter table 表名 change 列名 列名 数据类型 character set utf8;
-- 示例
alter table bb change name name varchar(20) character set utf8;
如果表中有多个包含中文的列,需要逐个修改。
方法二:建表时直接指定字符集(推荐)
sql
CREATE TABLE bb (
name VARCHAR(255),
age INT
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
或者更规范地,在列级别也指定:
sql
CREATE TABLE bb (
name VARCHAR(255) CHARACTER SET utf8,
age INT
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
方法三:修改数据库默认字符集
sql
-- 修改数据库默认字符集
alter database 数据库名 character set utf8;
七、举一反三
如果在修改列之后,插入中文仍然报错,可能是以下原因:
-
客户端连接字符集不一致:检查客户端编码
sqlshow variables like 'character_set_%';确保
character_set_client、character_set_connection、character_set_results都是utf8。 -
其他列仍使用 latin1:如果表中有多个字段需要存储中文,需要逐一检查并修改。
-
数据库或服务器级别的默认字符集 :可以通过修改 MySQL 配置文件(
my.cnf或my.ini)来设置全局默认字符集:ini[mysqld] character-set-server=utf8 collation-server=utf8_general_ci [client] default-character-set=utf8
八、总结
| 操作 | 命令 | 效果 |
|---|---|---|
| 修改表默认字符集 | alter table ... default character set utf8 |
只影响新列,不影响已有列 |
| 修改列字符集 | alter table ... change ... character set utf8 |
真正解决已有列的中文存储问题 |
| 建表时指定 | CREATE TABLE ... DEFAULT CHARSET=utf8 |
从根源上避免问题 |
建议 :在涉及中文存储的场景下,建表时务必显式指定 DEFAULT CHARSET=utf8,避免后续踩坑。
如果这篇文章对你有帮助,欢迎点赞收藏!有问题欢迎在评论区交流。