版本演變
| 版本 | VARCHAR 最大長度 | 備註 |
| < 5.0.3 | 255 | 超長需用 TEXT/BLOB |
| ≥ 5.0.3 | 65,535(實際 65,532 字節,含 1-2 字節長度前綴) | 可替代大部分 TEXT 場景 |
存儲機制核心差異
| 特性 | CHAR(N) | VARCHAR(N) |
| 長度 | 固定 N 字符 | 可變 0-N 字符 |
| 存儲 | 右側填充空格至 N | 實際長度 + 1/2 字節長度前綴 |
| 尾部空格 | **寫入填充、讀取刪除** | **保留**(標準 SQL) |
| 最大 N | 255 | 65,535(受行大小 65,535 字節限制) |
| 大小寫轉換 | 不轉換 | 不轉換 |
實際存儲對比(CHAR(4) vs VARCHAR(4),utf8mb4 環境)
| 插入值 | CHAR(4) 存儲 | CHAR 字節 | VARCHAR(4) 存儲 | VARCHAR 字節 |
'' | ' ' | 4 | '' | 1 |
'ab' | 'ab ' | 4 | 'ab ' | 3 |
'abcd' | 'abcd' | 4 | 'abcd' | 5 |
'abcdefgh' | 'abcd'(截斷+Warning) | 4 | 'abcd'(截斷+Warning) | 5 |
截斷與嚴格模式
- 預設(非嚴格):超長**截斷尾部**,產生 Warning。
- 嚴格模式(
STRICT_TRANS_TABLES / STRICT_ALL_TABLES):超長**報錯**,寫入失敗。
- 非空格字符被截斷 → Warning;嚴格模式 → Error。
比較與排序行為(PAD SPACE 特性)
所有 MySQL 校對規則屬於 PAD SPACE 類:**比較時忽略尾部空格**。
CREATE TABLE t (c CHAR(10), v VARCHAR(10));
INSERT INTO t VALUES ('Monty ', 'Monty ');
SELECT c = 'Monty', v = 'Monty' FROM t; -- 1, 1
⚠️ **唯一索引陷阱**:INSERT INTO t VALUES ('a'), ('a '); → **Duplicate entry**,因比較時尾部空格被忽略。
索引長度限制
- InnoDB 單列索引 ≤ 767 字節(5.7 預設),開啟
innodb_large_prefix=ON + ROW_FORMAT=DYNAMIC/COMPRESSED 可至 3072 字節。
VARCHAR(255) 在 utf8mb4 佔 767 字節(255×3+2),剛好卡邊界;VARCHAR(256) 會超限。
CHAR(255) 固定 765 字節,較安全。
選型建議
| 場景 | 推薦 | 理由 |
| 長度固定、極短(如 ISO 代碼、MD5、UUID) | CHAR | 固定長度、無長度前綴、索引效能略優 |
| 長度可變、平均長度遠小於最大值 | VARCHAR | 節省空間、減少 I/O |
| 需保留尾部空格(如密碼雜湊、Base64) | VARCHAR / BINARY | CHAR 會刪除尾部空格 |
| 超過 65KB 大文本 | TEXT/MEDIUMTEXT/LONGTEXT | VARCHAR 上限 65,535 字節 |
別名與相容性
CHAR BYTE = CHAR BINARY(二進制比較)。
ASCII 屬性 → latin1;UNICODE 屬性 → ucs2。