Python连接MySQL报incorrect string value错误的根本原因是字段字符集不支持UTF-8多字节,需将字段设为utf8mb4并显式指定charset='utf8mb4'连接参数,否则即使表结构正确仍会乱码。

Python连接MySQL报incorrect string value错误
这说明MySQL拒绝写入UTF-8编码的中文字节,根本原因是目标字段字符集不支持多字节——比如设成了latin1或旧版utf8(即utf8mb3)。utf8mb4才是MySQL里真正能存emoji和生僻汉字的完整UTF-8实现。
检查方式:执行SHOW CREATE TABLE your_table;,看字段定义里是否含CHARACTER SET utf8mb4。如果不是,必须改:
ALTER TABLE your_table MODIFY column_name VARCHAR(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;- 别只改表默认字符集,单个字段也得显式指定,否则新建字段仍继承旧设置
-
utf8mb4_unicode_ci比utf8mb4_general_ci更准,推荐优先用前者
pymysql.connect()必须传charset='utf8mb4'
即使数据库、表、字段全设成utf8mb4,Python连上去默认还是用latin1——这是PyMySQL的老默认,不是bug,是历史兼容行为。漏掉这个参数,INSERT时中文就会被当latin1解码再存,结果就是incorrect string value或查询出来是æ‘æˆ‘这类乱码。
正确写法:
立即学习“Python免费学习笔记(深入)”;
conn = pymysql.connect(
host='localhost',
user='root',
password='xxx',
database='test',
charset='utf8mb4', # 必须有,不能省
cursorclass=pymysql.cursors.DictCursor
)注意:charset参数值必须是utf8mb4,不是utf-8、utf8或UTF8MB4(大小写敏感)。
连接后立刻执行SET NAMES utf8mb4没用
有人试过在conn.cursor().execute("SET NAMES utf8mb4"),发现无效。因为PyMySQL在握手阶段已根据charset参数设置了character_set_client、character_set_connection、character_set_results三值,后续再SET只是覆盖会话层,但驱动内部缓存和编码路径早已按初始值走完了。
所以:
- 不要依赖SQL命令临时修正,
charset='utf8mb4'必须在connect()里声明 - 验证是否生效:连上后查
SELECT @@character_set_client, @@character_set_connection, @@character_set_results;,三者都应返回utf8mb4 - 如果返回
latin1,说明charset参数根本没生效,检查拼写、位置、是否被其他配置覆盖
已有数据是双重编码,光改字符集救不回来
如果之前连MySQL时没设charset,中文已经以错误方式存进去了(比如用UTF-8字节流当latin1存),那现在把表改成utf8mb4也没用——查出来还是乱码,HEX(column)会看到大量C3开头的字节(latin1误读UTF-8的典型特征),而正常中文UTF-8是E4、E5开头。
修复必须用转换链:
UPDATE your_table SET column_name = CONVERT(CAST(CONVERT(column_name USING latin1) AS BINARY) USING utf8mb4);
这条SQL本质是:先把错存的字节当latin1解码成字符串(得到可逆中间态)→转成二进制防丢 → 再用utf8mb4重新编码。不备份直接跑有风险,先CREATE TABLE backup AS SELECT * FROM your_table;。
真正麻烦的点在于:这种双重编码问题不会报错,只是显示乱,容易被忽略到上线后才发现——所以新项目务必从第一次connect()就带上charset='utf8mb4'。


















