MySQL错误1267是因collation不一致导致的硬性报错,必须使参与比较/连接/UNION的列使用完全相同的排序规则;可通过查询information_schema定位库、表、字段级collation差异,并优先统一数据库默认collation,再逐级调整表和字段,或在SQL中用COLLATE显式指定一致规则。

直接结论:这不是字符集问题,是 collation 不一致触发的硬性报错,必须让参与比较/连接/UNION 的列使用完全相同的排序规则,否则 MySQL 1267 错误必现。
查清哪些地方 collation 对不上
别猜,先定位。错误信息里写的两个 collation(比如 utf8mb4_0900_ai_ci 和 utf8mb4_unicode_ci)就是线索,但实际混用点可能藏在库、表、字段甚至临时结果里:
- 查库默认规则:
SELECT DEFAULT_COLLATION_NAME FROM information_schema.SCHEMATA WHERE SCHEMA_NAME = 'your_db_name'; - 查所有表的 collation:
SELECT TABLE_NAME, TABLE_COLLATION FROM information_schema.TABLES WHERE TABLE_SCHEMA = 'your_db_name'; - 查具体字段(尤其 JOIN 或 WHERE 里用到的):
SELECT COLUMN_NAME, COLLATION_NAME FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = 'your_db_name' AND TABLE_NAME IN ('t1', 't2') AND COLLATION_NAME IS NOT NULL; - 注意
IMPLICIT和COERCIBLE标签——前者来自列定义,后者常来自函数返回值(如SUBSTRING_INDEX()),它们也会参与 collation 推导
ALTER TABLE CONVERT TO 是最常用但有风险的操作
它会重写整张表、重建索引、锁表,大表执行时长不可控,且可能意外改掉你没注意到的字段类型:
- 只对单表生效,不改变数据库默认值,新字段仍可能继承旧 collation
-
ALTER TABLE t1 CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;会把所有VARCHAR/TEXT字段都带上新 collation,但ENUM/SET不受影响 - 如果某列是
latin1_swedish_ci,直接CONVERT TO可能导致乱码,应先确认原始数据编码是否真为 latin1 - 生产环境建议加
ALGORITHM=INPLACE, LOCK=NONE(MySQL 5.6+),但并非所有场景都支持
COLLATE 强制指定只适合临时救急
当不能动表结构(比如第三方库、只读实例、灰度中未全量上线),SQL 层加 COLLATE 是最快路径,但必须两边都加,且选型要谨慎:
- JOIN 场景:
ON t1.name COLLATE utf8mb4_unicode_ci = t2.name COLLATE utf8mb4_unicode_ci - UNION 场景:
SELECT col1 COLLATE utf8mb4_unicode_ci FROM t1 UNION SELECT col2 COLLATE utf8mb4_unicode_ci FROM t2 - 避免用
utf8mb4_general_ci:MySQL 8.0+ 已弃用,utf8mb4_unicode_ci兼容性更稳,utf8mb4_0900_as_cs区分大小写,按需选 - 函数返回值也要处理,例如
SUBSTRING_INDEX(filename, '.', 1) COLLATE utf8mb4_unicode_ci
统一从数据库层级开始才真正防复发
只改表不改库,下次建新表或新增字段时又会回归老 collation,所以优先级是:库 → 表 → 字段:
- 改库默认值:
ALTER DATABASE your_db_name CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; - 改现有表(不含字段类型变更):
ALTER TABLE t1 DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; - 改单个字段(最小影响):
ALTER TABLE t1 MODIFY COLUMN name VARCHAR(100) COLLATE utf8mb4_unicode_ci; - 注意:
DEFAULT CHARACTER SET不影响已有字段,仅控制后续新增字段;CONVERT TO才改存量数据
最容易被忽略的是函数返回值和临时表的 collation 来源——它们往往继承 collation_connection 或字段隐式类型,而不是你改过的表定义。线上修复前,务必在测试库跑一遍 EXPLAIN FORMAT=TRADITIONAL 看实际执行计划里的 collation 推导结果。


















