Collation不一致是导致排序规则冲突的根本原因,需检查字段级collation是否完全相同,通过INFORMATION_SCHEMA或sys.columns比对,再用ALTER TABLE修正字符集和排序规则。

怎么一眼看出是Collation在捣鬼
遇到 SQLSTATE[HY000] [1267] Illegal mix of collations 或 SQL Server 的 无法解决等于运算中的排序规则冲突,别急着改SQL——先确认是不是字段级 Collation 不一致。最直接的信号是:两表都有索引、字段类型相同(如都是 VARCHAR(64)),但 EXPLAIN 显示被驱动表的 key 为 NULL、type 是 ALL 或 index。这说明优化器主动弃用了索引,根本原因几乎就是 Collation 对不上。
查哪两个字段在“打架”
MySQL 里不能指望报错告诉你具体是哪张表哪个字段,得自己比:
- 用
INFORMATION_SCHEMA.COLUMNS一次性拉出两边字段的真实定义:SELECT table_name, column_name, character_set_name, collation_name FROM information_schema.COLUMNS WHERE table_schema = 'your_db' AND table_name IN ('t1', 't2') AND column_name = 'join_col'; - 重点看
collation_name是否**完全一致**:比如utf8mb4_unicode_ci≠utf8mb4_0900_ai_ci,哪怕字符集都是utf8mb4,也照样冲突 - SQL Server 则查系统视图:
sys.columns+sys.tables,语句类似:SELECT t.name, c.name, c.collation_name FROM sys.columns c JOIN sys.tables t ON c.object_id = t.object_id WHERE t.name IN ('table_a', 'table_b') AND c.collation_name IS NOT NULL;
ALTER TABLE MODIFY 才算真正修复
在 ON 子句里硬加 COLLATE 只能临时跑通,索引依然失效,而且埋下维护隐患。真正要改的是字段定义本身:
- 必须同时指定
CHARACTER SET和COLLATE,缺一不可:ALTER TABLE t2 MODIFY join_col VARCHAR(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
- 目标
COLLATE必须和关联表对应字段**一字不差**,别凭印象写成utf8mb4_general_ci或漏掉后缀 - 改完立刻执行
SHOW CREATE TABLE t2确认字段定义已更新——SHOW FULL COLUMNS有时会缓存旧值,不可信 - 大表操作前加
ALGORITHM=INPLACE(MySQL 8.0+ 支持时)可减少锁表时间,但需确保字段没全文索引等限制
别忘了连接层和 GROUP BY 场景
改完表结构不等于万事大吉。以下场景同样受 Collation 影响,且容易被跳过:
- 连接层污染:
@@collation_connection和字段 Collation 不一致,会导致字面量(如'abc')被错误解析。查状态:SELECT @@collation_connection, @@character_set_client;;JDBC 要补&collationConnection=utf8mb4_unicode_ci,pymysql 别传charset='utf8'(应为utf8mb4) - 外键约束:两边
FOREIGN KEY字段 Collation 不同,建表或插入就直接报ERROR 1005 -
UNION查询:所有子句中对应列的 Collation 必须完全一致,否则报同样错误 -
GROUP BY中文字段:若 A 表dept_name是utf8mb4_unicode_ci,B 表同名字段是utf8mb4_general_ci,同一部门名可能被分到不同组,聚合结果漂移
这些地方的字段往往不显式出现在 JOIN 条件里,但只要参与字符串比较逻辑,Collation 就必须对齐——漏掉任何一个,都可能让问题在某个低频路径里突然爆发。










