當執行 ALTER TABLE ... MODIFY COLUMN col TEXT 或新增 TEXT 欄位時拋出此錯,實際上並非該欄位過大,而是**整張表所有非大物件欄位 (non-BLOB/TEXT) 的定義長度總和超過 65535 位元組上限**。
VARCHAR(N) 在 5.0+ 版本實際儲存需 1-2 bytes 記錄長度,定義長度 N 字元 (utf8mb4 每字元 3-4 bytes)。VARCHAR(255)、VARCHAR(500) 等欄位,定義長度總和極易超過 65535 bytes 限制。not counting BLOBs 明確指出:BLOB/TEXT 不計入此限制 (它們只存 20 bytes 指標),**反而建議將超限的 VARCHAR 改為 TEXT/BLOB 類型以繞過行大小檢查**。某表擁有 200 個 VARCHAR(300) 欄位 (utf8mb4 最大 1200 bytes/欄),總定義長度約 240KB 遠超 64KB 上限,任意 ALTER 即報錯。
VARCHAR(N) 且 N ≤ 255 (或根據實際業務長度判斷) 的欄位。ALTER TABLE tbl MODIFY col TINYTEXT [CHARACTER SET utf8mb4]。TINYTEXT 固定儲存 255 字元上限,行內僅佔 1 byte 長度 + 20 bytes 指標,**大幅降低行定義長度佔用**。-- 範例:將多個小 varchar 改為 tinytext
ALTER TABLE my_table
MODIFY col_a TINYTEXT,
MODIFY col_b TINYTEXT,
MODIFY col_c TINYTEXT;
VARCHAR(300) 已超過 255,改為 TEXT (65535 上限) 合理;但 VARCHAR(100) 改 TEXT 會浪費儲存 (TEXT 固定 20 bytes 指標 + 溢頁儲存)。TINYTEXT 適合「業務長度確定 ≤ 255 字元」的欄位,行內開銷最小。ROW_FORMAT=DYNAMIC/COMPRESSED,可將大欄位自動溢頁,放寬行大小限制。utf8 (3 bytes/字) 而非 utf8mb4 (4 bytes/字) 可減少 25% 定義長度佔用。SELECT SUM(CHARACTER_MAXIMUM_LENGTH *
CASE CHARACTER_SET_NAME
WHEN 'utf8mb4' THEN 4 WHEN 'utf8' THEN 3 ELSE 1 END
) AS approx_max_bytes
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA='db' AND TABLE_NAME='tbl'
AND DATA_TYPE IN ('varchar','char','varbinary','binary');
若結果接近或超過 65535,即需優化欄位類型。
核心原則:**行定義長度預算 64KB 有限,善用 TINYTEXT/TEXT 將大欄位「移出行內」,保持核心表精簡高效。**