報錯 `ERROR 1267 (HY000): Illegal mix of collations (utf8mb4_general_ci,IMPLICIT) and (latin1_swedish_ci,COERCIBLE) for operation '='` 是字符集不一致的經典表現。本文從校對規則優先級原理出發,給出徹底解決方案與預防體系。
MySQL 解析表達式時,根據 **校對規則強制提升規則** 決定結果校對規則:
**衝突發生條件**:同一表達式中出現 **不同優先級且不兼容** 的校對規則,且無法按規則自動提升統一。
| 場景 | 錯誤示例 | 根因 |
|---|---|---|
| 跨表 JOIN/UNION | `t1.col_utf8 = t2.col_latin1` | 兩表欄位字符集/校對規則不同,均為 Implicit,優先級同級衝突 |
| 字串常數比較 | `WHERE col_utf8 = 'literal'` | 欄位 Implicit utf8mb4,常數 Coercible latin1 (舊版預設),無法自動提升 |
| 函數返回值比較 | `WHERE USER() = 'root'` | `USER()` 返回 utf8mb4 (系統變數),常數 Coercible latin1 |
| 存儲過程/觸發器變數 | `DECLARE v VARCHAR(10) DEFAULT 'a';` | 變數繼承資料庫/連線校對規則,與常數/參數衝突 |
-- 查詢層面修正
SELECT * FROM t1 JOIN t2 ON t1.col COLLATE utf8mb4_unicode_ci = t2.col COLLATE utf8mb4_unicode_ci;
-- 常數比較
WHERE col_utf8 = _utf8mb4'literal' -- 引入符 _charset'str' 指定常數字符集
WHERE col_utf8 = 'literal' COLLATE utf8mb4_unicode_ci
-- 連線建立後立即執行 (所有驅動支援)
SET NAMES utf8mb4 COLLATE utf8mb4_unicode_ci;
-- 等效於:
SET character_set_client = utf8mb4;
SET character_set_connection = utf8mb4;
SET character_set_results = utf8mb4;
SET collation_connection = utf8mb4_unicode_ci;
**效果**:連線層面統一後,字串常數、用戶變數、函數參數 (Coercible) 會自動提升為連線校對規則,消絕 90% 衝突。
-- 整表轉換 (資料實際重新編碼)
ALTER TABLE tbl_name CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
-- 僅修改預設 (不轉換現有資料,慎用)
ALTER TABLE tbl_name DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
-- 單欄位轉換
ALTER TABLE tbl_name MODIFY col_name VARCHAR(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
# my.cnf
[mysqld]
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci
init_connect = 'SET NAMES utf8mb4 COLLATE utf8mb4_unicode_ci'
skip-character-set-client-handshake # 強制忽略客戶端宣告
-- 1. 檢查 Server/資料庫/表/欄位/連線 當前字符集
SHOW VARIABLES LIKE 'character_set_%';
SHOW VARIABLES LIKE 'collation_%';
-- 2. 檢查具體表/欄位
SHOW CREATE TABLE tbl_name\G
SHOW FULL COLUMNS FROM tbl_name;
-- 3. 檢查常數/函數/變數 校對規則
SELECT COLLATION('literal'), COLLATION(USER()), COLLATION(@var);
-- 4. 找出庫內非 utf8mb4 表
SELECT TABLE_NAME, TABLE_COLLATION FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA = 'my_db' AND TABLE_COLLATION NOT LIKE 'utf8mb4%';
字符集衝突本質是**「協議雙方未達成一致」**。從 Server 預設、連線初始化、建表規範、CI 攔截四層防線同步推進,才能徹底消滅 `Illegal mix of collations`,讓團隊專注於業務價值而非編碼糾纏。