必须先查清collation分布再执行alter table,否则易改错表、漏字段或继承错误默认值;需用三句sql定位混用点,重点检查后缀是否一致;统一应按库→表→字段顺序操作,并注意触发器、连接层等隐含风险。

查清 collation 分布再动手
不先看现状就执行 ALTER TABLE,大概率改错表、漏字段,甚至让新字段继承旧库默认值。必须用这三句定位真实混用点:
SELECT DEFAULT_COLLATION_NAME FROM information_schema.SCHEMATA WHERE SCHEMA_NAME = 'your_db_name';SELECT TABLE_NAME, TABLE_COLLATION FROM information_schema.TABLES WHERE TABLE_SCHEMA = 'your_db_name';SELECT COLUMN_NAME, COLLATION_NAME FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = 'your_db_name' AND COLLATION_NAME IS NOT NULL;
重点不是“有没有 utf8mb4”,而是后缀是否一致:比如 utf8mb4_0900_as_cs 和 utf8mb4_unicode_ci 并存,或混着 utf8mb4_general_ci(已弃用)——只要参与 =、JOIN、IN 的列 collation 不同,1267 错误就随时触发。
统一 collation 要走「库→表→字段」路径
只改表不改库,新字段仍会继承旧库默认 collation;只改字段不设默认,后续 ADD COLUMN 又会复现问题。推荐顺序操作:
- 先改库:
ALTER DATABASE your_db_name CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; - 再批量改表(注意:
CONVERT TO会锁表重写,大表慎用):ALTER TABLE your_table CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; - 个别字段单独修正(避免全表重建):
ALTER TABLE your_table MODIFY COLUMN col_name VARCHAR(255) COLLATE utf8mb4_unicode_ci;
utf8mb4_unicode_ci 比 utf8mb4_0900_as_cs 兼容性更稳,MySQL 8.0+ 默认倾向后者,但业务涉及多语言排序时,前者更少踩坑。
临时绕过:在 SQL 中显式加 COLLATE
线上只读库、第三方表不能动、或发布窗口紧张时,这是最快止血方式。但必须两边都加,且 collation 名称完全一致:
-
JOIN场景:ON t1.name COLLATE utf8mb4_unicode_ci = t2.name COLLATE utf8mb4_unicode_ci -
IN子查询:WHERE cInvName COLLATE utf8mb4_unicode_ci IN (SELECT SUBSTRING_INDEX(FileName, '.', 1) COLLATE utf8mb4_unicode_ci FROM fileinfo) -
UNION报错:SELECT 'a' COLLATE utf8mb4_unicode_ci UNION SELECT 'b' COLLATE utf8mb4_unicode_ci
别用 CONVERT(col USING 'utf8mb4') 代替 COLLATE:它改的是字节序列,返回 CHAR 类型,索引失效、性能下降,且无法复用字段原有校对逻辑。
触发器和存储过程里最容易被忽略
即使表结构全统一,触发器仍可能报错——因为它的执行环境继承的是会话级的 @@collation_connection,不是字段定义的 collation。常见崩点:
-
IF NEW.name = 'admin'→ 必须写成IF NEW.name COLLATE utf8mb4_unicode_ci = 'admin' COLLATE utf8mb4_unicode_ci - 局部变量声明没指定 collation:
DECLARE v_name VARCHAR(50);→ 应改为DECLARE v_name VARCHAR(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; - 函数参数传入未对齐:
UPPER(NEW.name)→ 改为UPPER(NEW.name COLLATE utf8mb4_unicode_ci)
连接层也得同步:SET NAMES utf8mb4 COLLATE utf8mb4_unicode_ci; 才能确保触发器运行时上下文真正对齐。否则改完表,触发器一跑还是崩。











