直接修改表字符集不会更新字段字符集,需用CONVERT TO或逐字段调整;推荐ALTER TABLE ... CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci,并确保数据库默认字符集、连接层及ORM配置均为utf8mb4。

修改已有表的字符集为 utf8mb4
直接改表字符集不会自动更新已有字段的字符集,必须显式指定 CONVERT TO CHARACTER SET 或逐字段调整。否则新插入的 emoji 或四字节中文仍会报错 Incorrect string value。
推荐用这条命令一次性转换表结构和所有文本字段:
ALTER TABLE `your_table_name` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
注意点:
- 执行前确保数据库默认字符集已是
utf8mb4(查SHOW VARIABLES LIKE 'character_set_database';) - 该操作会锁表,大表建议在低峰期执行,或分步做(先改字段再改表)
- 如果字段有全文索引,
CONVERT TO可能失败,需先删索引、转换、再重建 - 时间类型(
DATETIME)、数值型字段不受影响,无需额外处理
单独修改某个字段的字符集
当只要改某几个字段(比如只调 title 和 content),或者 CONVERT TO 失败时,用 MODIFY 或 CHANGE 更可控。
例如把 name 字段从 utf8 改成 utf8mb4:
ALTER TABLE `your_table_name` MODIFY `name` VARCHAR(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
关键细节:
- 必须重写整个字段定义(类型、长度、是否
NOT NULL等都要显式写出),否则可能丢失约束 - 如果原字段是
TEXT类型,记得用TEXT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci,别漏掉CHARACTER SET - 对
ENUM或SET字段,要重新列出所有值,并确保值本身能被utf8mb4编码
创建新表时就设对字符集
避免后期迁移,建表语句里必须显式声明字符集和排序规则,不能依赖数据库默认值。
正确写法示例:
CREATE TABLE `new_table` ( `id` INT PRIMARY KEY, `content` TEXT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
常见疏漏:
- 只写了表级
DEFAULT CHARSET=utf8mb4,但字段定义里没提CHARACTER SET,此时字段仍按旧规则继承(取决于 MySQL 版本和配置) - 用了
utf8mb4_general_ci—— 这个排序规则已弃用,MySQL 8.0+ 默认不推荐,统一用utf8mb4_unicode_ci或utf8mb4_0900_as_cs - 没配
innodb_large_prefix = ON(MySQL 5.7.7+ 默认开启),否则TEXT/VARCHAR超长字段建索引可能失败
客户端连接也得配 utf8mb4
表和字段全改成 utf8mb4 后,如果应用连 MySQL 时没声明字符集,还是会退化成 utf8(即 utf8mb3),导致写入截断或报错。
检查并设置连接层字符集:
- 连接串里加参数:如 JDBC 加
?characterEncoding=utf8mb4;PHP PDO 加PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8mb4" - MySQL 配置文件中确认
[client]和[mysql]段有default-character-set = utf8mb4 - 运行时验证:
SHOW VARIABLES LIKE 'character_set_client';和SHOW VARIABLES LIKE 'collation_connection';必须都是utf8mb4_*
最常被忽略的是 ORM 层配置(比如 Django 的 OPTIONS={'charset': 'utf8mb4'})或连接池初始化 SQL,漏掉一个环节,前面所有表结构调整都白做。


















