MySQL 整數類型定義中的 INT(M)、SMALLINT(M) 等,M 僅為顯示寬度,不影響儲存範圍。本文通過實測驗證預設寬度、ZEROFILL 效果、越界截斷行為與符號位對範圍的決定性影響。
CREATE TABLE c (id INT NOT NULL, name CHAR NOT NULL);
DESC c;
+-------+---------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+---------+------+-----+---------+-------+
| id | int(11) | NO | | NULL | |
| name | char(1) | NO | | NULL | |
+-------+---------+------+-----+---------+-------+
修改類型觀察預設寬度變化:
| 類型 | 預設顯示寬度 | 儲存字節 | 有符號範圍 | 無符號範圍 |
|---|---|---|---|---|
| TINYINT | 4 | 1 | -128 ~ 127 | 0 ~ 255 |
| SMALLINT | 6 | 2 | -32768 ~ 32767 | 0 ~ 65535 |
| MEDIUMINT | 9 | 3 | -8388608 ~ 8388607 | 0 ~ 16777215 |
| INT | 11 | 4 | -2147483648 ~ 2147483647 | 0 ~ 4294967295 |
| BIGINT | 20 | 8 | -9223372036854775808 ~ 9223372036854775807 | 0 ~ 18446744073709551615 |
CREATE TABLE t (id INT(5) ZEROFILL);
INSERT INTO t VALUES (1), (12), (123), (1234), (12345);
SELECT * FROM t;
+-------+
| id |
+-------+
| 00001 |
| 00012 |
| 00123 |
| 01234 |
| 12345 |
+-------+
ZEROFILL 隱含 UNSIGNED,負數插入會報錯或截斷為 0。
CREATE TABLE c (id TINYINT, name CHAR(1));
INSERT INTO c VALUES (300, 'chen');
-- Warning: Out of range value for column 'id' at row 1
-- Warning: Data truncated for column 'name' at row 1
SELECT * FROM c;
+------+------+
| id | name |
+------+------+
| 127 | c | -- TINYINT 有符號最大值 127
+------+------+
再次插入 320,結果同樣為 127。
結論:嚴格模式 (STRICT_ALL_TABLES) 下會直接報錯回滾;非嚴格模式下截斷至邊界值並發出 Warning。
實測中 TINYINT 最大只到 127,原因是預設為 SIGNED(有符號),最高位作為符號位。
若需 0~255 範圍,必須顯式聲明:
CREATE TABLE t (id TINYINT UNSIGNED); -- 範圍 0 ~ 255
sql_mode=STRICT_TRANS_TABLES,STRICT_ALL_TABLES,讓越界直接報錯而非靜默截斷。理解顯示寬度與儲存範圍的解耦關係,是設計高效、正確表結構的基礎功。