MySQL 插入中文报错 ERROR 1366 (HY000): Incorrect string value 的解决办法

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;

七、举一反三

如果在修改列之后,插入中文仍然报错,可能是以下原因:

  1. 客户端连接字符集不一致:检查客户端编码

    sql 复制代码
    show variables like 'character_set_%';

    确保 character_set_client、character_set_connection、character_set_results 都是 utf8。

  2. 其他列仍使用 latin1:如果表中有多个字段需要存储中文,需要逐一检查并修改。

  3. 数据库或服务器级别的默认字符集 :可以通过修改 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,避免后续踩坑。


如果这篇文章对你有帮助,欢迎点赞收藏!有问题欢迎在评论区交流。

相关推荐
ClickHouseDB2 小时前
ClickHouse Cloud 与 Snowflake 实时性价比对比:CostBench 测试中的 412 倍差距来
运维·数据库·系统架构
m0_639906942 小时前
Redis入门|五种数据结构、使用场景、持久化RDB&AOF
数据结构·数据库·redis
时间售卖铺3 小时前
触发器与函数实战:MySQL高效编程秘诀
运维·数据库·mysql·云原生
qetfw3 小时前
UOS MariaDB 数据库:安装、最小权限与备份验证
linux·数据库·mariadb·uos
数智园区合作社4 小时前
问数平台怎么把同一个指标锁成一个数
大数据·数据库·人工智能·ai
lbb 小魔仙5 小时前
Windows搭建PaddleOCR+飞书Webhook自动打卡通知机器人:识别、推送与远程触发完整教程
数据库·人工智能·prometheus·时序数据库
captain3766 小时前
MyBatis操作数据库(入门2)
java·数据库·spring boot·后端·spring·mybatis
心中有你02146 小时前
Java实现Dijkstra最短路径算法(邻接表 + 优先队列)
java·数据库·算法
龙亘川6 小时前
综合素质评价业务建模:从过程性评价到成长档案全链路闭环
数据库·智慧城市·数据可视化
数据库小组6 小时前
NineData 实战教程:MySQL 5.5 数据迁移同步到 MySQL 8.0(跨版本升级)
数据库·mysql·mysql优化·数据库开发·数据库迁移·版本升级·数据复制