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,避免后续踩坑。


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

相关推荐
Cloud云卷云舒13 小时前
云卷云舒:从Oracle/MySQL迁移到HaishanDB:迁移评估工具核心技术拆解
mysql·oracle·ai-native·haishandb·信创数据库替换
憧憬成为web高手13 小时前
皮卡丘靶场速通--sql 2
数据库·sql·mybatis
段一凡-华北理工大学14 小时前
向量数据库实战:选型、调优与落地~系列文章12:文本分块策略实战:chunk_size 怎么选?重叠多少?
开发语言·数据库·后端·oracle·rust·工业智能体·高炉智能化
oradh16 小时前
Oracle XTTS实现跨版本迁移和升级(Oracle 11g单库升级至19C RAC集群)
数据库·oracle·11g升级19c·xtts跨版本迁移和升级
用户713335851562416 小时前
MySQL - 事务、redo/undo 日志与 MVCC
mysql
z1234567898617 小时前
2026最新两款AI编程工具深度对比实测
java·数据库·ai编程
程序猿DD17 小时前
一个 API Key,统一调用大模型、生图和联网搜索
数据库·网关
java_logo17 小时前
Docker Compose 部署 ClickHouse:快速搭建高性能列式数据库
数据库·clickhouse·docker·列式数据库·轩辕镜像·高性能数据库·clickhouse部署教程
用户713335851562417 小时前
MySQL - InnoDB 的 Buffer Pool
mysql
TlSfoward18 小时前
抓包代理链路下的 TLS 指纹变化分析 TLSFOWARD抓包工具
数据库·爬虫·网络协议·搜索引擎·php