本文通過實際 SQL 執行與結果分析,驗證 MySQL 核心字符類型(CHAR、VARCHAR、TEXT/BLOB)及精確數值類型(DECIMAL)的存儲行為、長度限制、字符集影響及物理存儲特性,為表結構設計提供一手實證依據。
定義: CHAR(M),M 為字符數,長度 = M × 字符編碼字節數,M 最大 255。
驗證過程:
mysql> create table t1(name char(256)) default charset=utf8;
ERROR 1074 (42000): Column length too big for column 'name' (max = 255); use BLOB or TEXT instead
mysql> create table t1(name char(255)) default charset=utf8;
Query OK, 0 rows affected (0.06 sec)
mysql> insert into t1 values(repeat('整',255));
Query OK, 1 row affected (0.00 sec)
mysql> select length(name), char_length(name) from t1;
+--------------+-------------------+
| length(name) | char_length(name) |
+--------------+-------------------+
| 765 | 255 |
+--------------+-------------------+
結論: UTF8 下每字符 3 字節,255 字符佔 765 字節。LENGTH() 返回字節數,CHAR_LENGTH() 返回字符數。
定義: VARCHAR(M),M 為字符數,長度 = M × 字符編碼字節數。**核心限制:行總長度 ≤ 65535 字節**(不含 BLOB/TEXT)。
mysql> create table t1(name varchar(65535)); ERROR 1118 (42000): Row size too large... max = 65535 mysql> create table t1(name varchar(65532)); Query OK, 0 rows affected (0.08 sec)
最大可定義 65532 字節(扣除元數據開銷)。
mysql> create table t1(name varchar(65532)) default charset=utf8; ERROR 1074 (42000): Column length too big... max = 21845 mysql> create table t1(name varchar(21844)) default charset=utf8; Query OK, 0 rows affected (0.07 sec)
最大字符數 21844(21844 × 3 = 65532 字節)。
mysql> create table t1(name varchar(65528), hiredate datetime) default charset=latin1; ERROR 1118 (42000): Row size too large... mysql> create table t1(name varchar(65527), hiredate datetime) default charset=latin1; Query OK, 0 rows affected (0.01 sec)
DATETIME 佔 5 字節(MySQL 5.6.4+),驗證行總長度確為 65535 字節上限。
定義長度映射規則:
| 指定長度範圍(字節) | 實際類型 |
|---|---|
| < 2⁸ (256) | TINYTEXT / TINYBLOB |
| < 2¹⁶ (65536) | TEXT / BLOB |
| < 2²⁴ (16777216) | MEDIUMTEXT / MEDIUMBLOB |
| < 2³² | LONGTEXT / LONGBLOB |
驗證:
mysql> create table t1(name text(255)); Query OK... SHOW CREATE TABLE t1\G -- 輸出: `name` tinytext mysql> create table t2(name text(256)); Query OK... SHOW CREATE TABLE t2\G -- 輸出: `name` text
mysql> create table t1(name text) default charset=utf8;
Query OK
mysql> insert into t1 values(repeat('整',21846));
ERROR 1406 (22001): Data too long for column 'name' at row 1
mysql> insert into t1 values(repeat('整',21845));
Query OK, 1 row affected
UTF8 下 TEXT 最大存 21845 字符(65535 字節 / 3),受內部行格式限制,非 65535 字符。
官方存儲算法: 每 9 位十進制數字打包進 4 字節。整數部分與小數部分**分別計算**存儲。剩餘位數存儲對照表:
| 剩餘位數 | 字節數 |
|---|---|
| 0 | 0 |
| 1-2 | 1 |
| 3-4 | 2 |
| 5-6 | 3 |
| 7-9 | 4 |
驗證案例:
DECIMAL(6,5):整數 1 位 → 1 字節,小數 5 位 → 3 字節,**共 4 字節**DECIMAL(9,0):整數 9 位 → 4 字節,**共 4 字節**DECIMAL(8,3):整數 5 位 → 3 字節,小數 3 位 → 2 字節,**共 5 字節**驗證方法:InnoDB Table Monitor
mysql> create table t2(id decimal(6,5)); mysql> create table t3(id decimal(9,0)); mysql> create table t4(id decimal(8,3)); mysql> CREATE TABLE innodb_table_monitor (a INT) ENGINE=INNODB; -- 啟用監視器 -- 結果輸出至錯誤日志,解析確認上述存儲字節數
| 類型 | M 含義 | 最大字符數限制 | 本質限制 |
|---|---|---|---|
| CHAR | 字符數 | 255 | 固定長度,列級限制 |
| VARCHAR | 字符數 | Latin1: 65532 / UTF8: 21844 | 行總長度 ≤ 65535 字節(不含 BLOB/TEXT) |
| TEXT/BLOB | 字節數 | TINY: 255 / TEXT: 65535 / MEDIUM: 16M / LONG: 4G | 類型自定義上限,不受行長度限制 |
設計建議:
通過實測驗證掌握數據類型真實行為,是設計高效、無隱患表結構的基石。