MySQL 插入中文报错 ERROR 1366 (HY000): Incorrect string value 的完整解决记录
一、问题现象
今天在 MySQL 中新建了一个数据库和表,准备插入一些测试数据。当插入英文字符时一切正常,但插入中文时却报错了。
1. 复现步骤
-- 创建数据库mysql>createdatabaseaa;Query OK,1rowaffected(0.00sec)-- 切换数据库mysql>useaa;Databasechanged-- 创建测试表mysql>createtablebb(namevarchar(255),ageint);Query OK,0rowsaffected(0.01sec)-- 尝试插入中文数据(报错!)mysql>insertintobbvalues('张三',23);ERROR1366(HY000): Incorrect stringvalue:'\xE5\xBC\xA0\xE4\xB8\x89'forcolumn'name'atrow1-- 插入英文数据(正常)mysql>insertintobbvalues("zhangsan",23);Query OK,1rowaffected(0.00sec)2. 错误信息解读
- 错误码:
ERROR 1366 (HY000) - 错误提示:
Incorrect string value: '\xE5\xBC\xA0\xE4\xB8\x89' for column 'name' at row 1 - 含义:第 1 行的
name列的字符串值不正确,无法识别中文编码。
二、问题排查
1. 查看表结构
mysql>showcreatetablebb;输出结果:
+-------+-----------------------------------------------------------------------------------------------------------------------------+|Table|CreateTable|+-------+-----------------------------------------------------------------------------------------------------------------------------+|bb|CREATETABLE`bb`(`name`varchar(255)DEFAULTNULL,`age`int(11)DEFAULTNULL)ENGINE=InnoDBDEFAULTCHARSET=latin1|+-------+-----------------------------------------------------------------------------------------------------------------------------+发现问题:表的默认字符集是latin1,而不是utf8。latin1是单字节编码,无法存储中文。
三、第一次尝试:修改表的默认字符集
参考网上的方法,先尝试修改表的默认字符集:
mysql>altertablebbdefaultcharactersetutf8;Query OK,0rowsaffected(0.00sec)Records:0Duplicates:0Warnings:0修改后再次查看表结构:
mysql>showcreatetablebb;输出结果:
+-------+------------------------------------------------------------------------------------------------------------------------------------------------+|Table|CreateTable|+-------+------------------------------------------------------------------------------------------------------------------------------------------------+|bb|CREATETABLE`bb`(`name`varchar(255)CHARACTERSETlatin1DEFAULTNULL,`age`int(11)DEFAULTNULL)ENGINE=InnoDBDEFAULTCHARSET=utf8|+-------+------------------------------------------------------------------------------------------------------------------------------------------------+注意:虽然表的默认字符集已经变成了utf8,但name列的字符集仍然是latin1!
再次插入中文测试:
mysql>insertintobbvalues("张三",23);ERROR1366(HY000): Incorrect stringvalue:'\xE5\xBC\xA0\xE4\xB8\x89'forcolumn'name'atrow1结论:只修改表的默认字符集是不够的,列的字符集没有随之改变。
四、第二次尝试:修改列的字符集
需要单独修改name列的字符集为utf8:
mysql>altertablebb change name namevarchar(20)charactersetutf8;Query OK,1rowaffected(0.04sec)Records:0Duplicates:0Warnings:0再次插入中文:
mysql>insertintobbvalues("张三",23);Query OK,1rowaffected(0.00sec)成功!
五、验证结果
mysql>select*frombb;+----------+------+|name|age|+----------+------+|zhangsan|23||张三|23|+----------+------+2rowsinset(0.00sec)中文数据已经成功插入并正常显示。
六、问题总结
核心原因
MySQL 中,表级别的默认字符集和列级别的字符集是分开的:
| 层级 | 作用范围 | 说明 |
|---|---|---|
| 数据库级别 | 整个数据库 | 影响新建表的默认字符集 |
| 表级别 | 整张表 | 影响新建列的默认字符集 |
| 列级别 | 单个字段 | 决定该字段实际存储的编码 |
当使用alter table ... default character set utf8时,只修改了表级别的默认字符集,已经存在的列的字符集不会自动改变。
正确解决方法
方法一:修改已有列的字符集(适用于已有数据的表)
-- 修改指定列的字符集altertable表名 change 列名 列名 数据类型charactersetutf8;-- 示例altertablebb change name namevarchar(20)charactersetutf8;如果表中有多个包含中文的列,需要逐个修改。
方法二:建表时直接指定字符集(推荐)
CREATETABLEbb(nameVARCHAR(255),ageINT)ENGINE=InnoDBDEFAULTCHARSET=utf8;或者更规范地,在列级别也指定:
CREATETABLEbb(nameVARCHAR(255)CHARACTERSETutf8,ageINT)ENGINE=InnoDBDEFAULTCHARSET=utf8;方法三:修改数据库默认字符集
-- 修改数据库默认字符集alterdatabase数据库名charactersetutf8;七、举一反三
如果在修改列之后,插入中文仍然报错,可能是以下原因:
客户端连接字符集不一致:检查客户端编码
showvariableslike'character_set_%';确保
character_set_client、character_set_connection、character_set_results都是utf8。其他列仍使用 latin1:如果表中有多个字段需要存储中文,需要逐一检查并修改。
数据库或服务器级别的默认字符集:可以通过修改 MySQL 配置文件(
my.cnf或my.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,避免后续踩坑。
如果这篇文章对你有帮助,欢迎点赞收藏!有问题欢迎在评论区交流。