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,而不是 utf8latin1 是单字节编码,无法存储中文。


三、第一次尝试:修改表的默认字符集

参考网上的方法,先尝试修改表的默认字符集:

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_clientcharacter_set_connectioncharacter_set_results 都是 utf8

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

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


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

相关推荐
qq_349317482 小时前
CSS如何实现Bootstrap进度条自定义动画_利用keyframe关键帧
jvm·数据库·python
2401_871492852 小时前
Python机器学习怎么防止数据泄漏_确保Scaler在Pipeline内拟合
jvm·数据库·python
【心态好不摆烂】2 小时前
数据库基础
数据库
Bert.Cai2 小时前
MySQL UPPER()函数详解
数据库·mysql
2301_818008442 小时前
MySQL怎样在触发器中引用新旧数据行_NEW与OLD关键字详解
jvm·数据库·python
langsiming2 小时前
【无标题】
java·开发语言·数据库
Boop_wu3 小时前
[Java EE 进阶]Mybatis进阶(动态SQL)
java·数据库·maven·mybatis
Elastic 中国社区官方博客3 小时前
使用 EDOT Browser 和 Kibana 进行 OpenTelemetry 浏览器端埋点
大数据·服务器·数据库·elasticsearch·搜索引擎·单元测试·可用性测试
星轨zb3 小时前
为什么Mysql需要索引以及如何应用到项目中
数据库·mysql