不能用 alter database 一键修改字符集,它只改数据库默认值,不影响已有表和字段;必须用 convert to 生成 alter table 语句逐表转换,并显式指定 character set 和 collate,加反引号包裹表名,且需处理外键和特殊排序规则。

直接结论:不能用 ALTER DATABASE 一键改完
ALTER DATABASE 只改默认字符集,对已有表的 DEFAULT CHARSET 和字段实际 COLLATION 完全无效。执行后表结构、字段内容、UNION/JOIN 行为全都不变,照样报 ERROR 1271 (HY000): Illegal mix of collations。
必须用 CONVERT TO 生成并执行 ALTER TABLE
核心逻辑是:查 information_schema.tables,拼出带反引号和显式 COLLATE 的 ALTER TABLE ... CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci 语句。不指定 COLLATE 时,MySQL 会按 server 默认(如 utf8mb4_0900_ai_ci)选,跟旧库行为不兼容。
- 必须加反引号包裹表名:
`table_name`,否则含关键字(如order、group)或中划线的表会报语法错误 - 必须同时写
CHARACTER SET和COLLATE,缺一不可 -
CONVERT TO会重写所有字符型字段(VARCHAR、TEXT等),但跳过INT、DATETIME等非字符字段 - 如果某字段之前显式指定了
COLLATE utf8mb4_bin,CONVERT TO也会把它改成目标COLLATE——这是默认行为,若需保留特殊排序规则(如大小写敏感),得单独用MODIFY COLUMN
执行前务必确认当前字符集状态
先跑这几条语句,避免盲目操作:
SHOW CREATE DATABASE your_db_name;
SELECT table_name, table_collation FROM information_schema.tables WHERE table_schema = 'your_db_name' AND table_type = 'BASE TABLE';
重点关注两点:
- 数据库是否已是
utf8mb4?不是的话先ALTER DATABASE设默认值(只影响新建表) - 哪些表的
table_collation是latin1_swedish_ci、utf8_general_ci或混用不同utf8mb4_*,这些才是要批量处理的目标
容易被忽略的关键点
真正麻烦的从来不是生成语句,而是字段级 COLLATION 不一致带来的隐式转换风险。比如同一张表里 title 字段用 utf8mb4_unicode_ci,而 slug 用了 utf8mb4_bin,CONVERT TO 会统一改掉——这多数时候是好事;但如果你依赖 _bin 做大小写敏感匹配,就得在改完后手动把 slug 再 MODIFY 回去。另外,有外键约束的表可能在 CONVERT TO 时失败,得先 DROP 外键再重建。











