MySQL 字元集設定呈現層級繼承與獨立覆蓋機制:
character_set_server,啟動預設DEFAULT CHARSET,建庫指定,僅作為後續建表的預設值DEFAULT CHARSET,建表指定,僅作為後續加欄位的預設值CHARACTER SET,建表/加欄位時具體指定,**最終決定資料實際儲存編碼**關鍵認知:**修改上層預設值,不會自動變更下層已建立物件的編碼**。
-- 1. 建表指定 latin1
CREATE TABLE `category` (
`Id` binary(16) NOT NULL,
`UniqueName` varchar(64) NOT NULL,
`Name` varchar(64) NOT NULL,
`CreatedAt` datetime NOT NULL,
PRIMARY KEY (`Id`),
KEY `IX_Category_UniqueName_CreatedAt` (`UniqueName`,`CreatedAt`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
-- 2. 修改表預設字元集為 utf8
ALTER TABLE `category` DEFAULT CHARSET=utf8;
-- 3. 查看 DDL 變化
SHOW CREATE TABLE `category`\G
-- 結果:
-- 表級 DEFAULT CHARSET=utf8
-- 但現有欄位 UniqueName、Name 仍保持 character set latin1
-- 新增欄位才會預設 utf8
| 層級 | 查看指令 | 關鍵輸出 |
|---|---|---|
| 伺服器 | SHOW VARIABLES LIKE 'character_set_%'; |
character_set_server, character_set_database, character_set_client 等 |
| 資料庫 | SHOW CREATE DATABASE db_name; |
DEFAULT CHARACTER SET utf8mb4 |
| 資料表 | SHOW TABLE STATUS FROM db_name LIKE 'tbl_name'; |
Collation 欄位 (如 utf8mb4_general_ci) |
| 欄位 | SHOW FULL COLUMNS FROM tbl_name; |
Collation 欄位顯示各欄位實際編碼 |
| 項目 | utf8 (MySQL 別名 utf8mb3) | utf8mb4 |
|---|---|---|
| Unicode 覆蓋 | 僅 BMP (基本多語言平面),U+0000~U+FFFF | 完整 Unicode,含增補平面 (Emoji、生僻字) |
| 最大位元組/字元 | 3 bytes | 4 bytes |
| 索引長度限制 | 767 bytes (InnoDB 預設) → 255 字元 | 767 bytes → 191 字元 (需 innodb_large_prefix=ON 3072 bytes → 768 字元) |
| 建議 | 棄用,無法儲存 Emoji、生僻字 | 新專案強制標準,MySQL 8.0 預設 |
-- 1. 修改資料庫預設
ALTER DATABASE `mydb` CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci;
-- 2. 修改表預設 + 所有現有欄位 (需逐表執行)
ALTER TABLE `mydb`.`table1` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
-- CONVERT TO 會同時修改表預設、所有文字欄位編碼、資料重新編碼
-- 3. 僅修改表預設 (不影響現有欄位)
ALTER TABLE `mydb`.`table2` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
-- 4. 修改單一欄位
ALTER TABLE `mydb`.`table3` MODIFY `col1` VARCHAR(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL;
MySQL 字元集機制的核心誤區在於**以為修改上層預設值會級聯修改下層實際編碼**。實際上,**欄位層編碼才是資料儲存的最終決定權**。建立新專案時,全鏈路強制 utf8mb4;接手舊系統時,**逐欄位驗證並修正**,配合 CONVERT TO CHARACTER SET 批次遷移,徹底根治亂碼隱患。