TINYINT~BIGINT);FLOAT/DOUBLE/DECIMAL 不支援。TINYINT -128~127 → UNSIGNED 0~255)。| 類型 | 位元組 | 有號範圍 | 無號範圍 |
|---|---|---|---|
| TINYINT | 1 | -128 ~ 127 | 0 ~ 255 |
| SMALLINT | 2 | -32768 ~ 32767 | 0 ~ 65535 |
| MEDIUMINT | 3 | -8388608 ~ 8388607 | 0 ~ 16777215 |
| INT | 4 | -2147483648 ~ 2147483647 | 0 ~ 4294967295 |
| BIGINT | 8 | -9223372036854775808 ~ 9223372036854775807 | 0 ~ 18446744073709551615 |
MySQL 為追求速度,整數運算直接在二進制層面進行。UNSIGNED 欄位做 0 - 1 會產生極大正數 (補數回繞),而非報錯或截斷。
UPDATE `user` SET `tk` = `tk` - 8 WHERE `id` = 1330; -- tk 為 UNSIGNED,若 tk < 8 會溢出
UPDATE `user`
SET `tk` = CONVERT(`tk` + (-8), SIGNED)
WHERE `id` = 1330;
CONVERT(expr, SIGNED) 將運算中間結果視為有號整數,允許負數暫存,寫回時再隱式轉回 UNSIGNED (若結果 < 0 會截斷為 0 或報錯,視 SQL_MODE 而定)。CAST(expr AS SIGNED) 效果相同。if (current >= deduct) 再發 SQL,避免資料庫層處理邊界。CONVERT(col + delta, SIGNED) 模式。SIGNED BIGINT,保留負數檢查彈性;純計數器 (ID、PV) 才用 UNSIGNED。SQL_MODE=STRICT_TRANS_TABLES,NO_UNSIGNED_SUBTRACTION 讓溢出直接報錯而非靜默回繞。UNSIGNED 是儲存空間優化利器,但減法溢出是隱形坑。採用「應用層預檢 + SQL 簽名轉換 + 嚴格 SQL_MODE」三層防護,既享受空間紅利,又杜絕補數陷阱。