先查清当前 collation 分布:用 select default_collation_name from information_schema.schemata、select table_name, table_collation from information_schema.tables、select column_name, collation_name from information_schema.columns 定位混用 utf8mb4_general_ci/unicode_ci/0900_as_cs 等不一致规则的字段,避免误改或遗漏。

查清当前 collation 分布情况
不先看现状就改,容易改错表或漏掉字段。用这几条语句快速定位问题源头:
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 TABLE_NAME = 'your_table' AND COLLATION_NAME IS NOT NULL;
重点看结果里是否混着 utf8mb4_general_ci、utf8mb4_unicode_ci、utf8mb4_0900_as_cs 这类不同后缀的排序规则——只要参与比较(=、IN、JOIN、UNION)的列 collation 不一致,1267 错误就随时可能触发。
ALTER DATABASE + ALTER TABLE 一次性对齐
推荐优先走「库→表→字段」自上而下的统一路径,避免只改表却忽略新字段继承旧库默认值的问题:
- 先改数据库默认 collation:
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; - 如果只需改个别字段(比如某列是
latin1_swedish_ci),单独执行:ALTER TABLE your_table MODIFY COLUMN col_name VARCHAR(255) COLLATE utf8mb4_unicode_ci;
别用 utf8mb4_general_ci ——它已弃用,MySQL 8.0+ 默认是 utf8mb4_0900_as_cs 或 utf8mb4_unicode_ci,后者兼容性更稳。
临时绕过但不推荐的 COLLATE 强制指定
当无法立刻修改结构(比如线上只读库、第三方表不能动),可在 SQL 中显式加 COLLATE 对齐:
- JOIN 场景:
ON t1.name COLLATE utf8mb4_unicode_ci = t2.name COLLATE utf8mb4_unicode_ci - 子查询 IN:
WHERE cInvName COLLATE utf8mb4_unicode_ci IN (SELECT FileName COLLATE utf8mb4_unicode_ci FROM fileinfo) - UNION 报错时:
SELECT 'a' COLLATE utf8mb4_unicode_ci UNION SELECT 'b' COLLATE utf8mb4_unicode_ci
这法子能跑通,但每次写 SQL 都要手动补,维护成本高,且容易漏写导致偶发报错。只适合救急,不是长期方案。
连接层和客户端也得同步检查
即使库表字段全统一了,如果应用连接 MySQL 时没声明字符集,或者 JDBC URL 缺 useUnicode=true&characterEncoding=utf8mb4,照样可能触发隐式转换冲突:
- 确认 MySQL 配置文件
my.cnf有:[client] default-character-set = utf8mb4和[mysqld] character-set-server = utf8mb4 - PHP 的
mysqli_set_charset($conn, 'utf8mb4')或 PDO DSN 加;charset=utf8mb4 - Java 的 JDBC URL 示例:
jdbc:mysql://localhost:3306/db?useUnicode=true&characterEncoding=utf8mb4&serverTimezone=UTC
collation 冲突常被当成纯 SQL 问题,其实根源可能在连接初始化阶段就埋下了——这点最容易被忽略。











