MySQL 中 DATE、DATETIME、TIMESTAMP 三大時間型別(加上 INT 存儲時間戳共四種)常讓開發者困惑。本文從儲存範圍、時區行為、自動更新、空間佔用、精度五個維度深度對比,助您根據業務場景做出正確選型。
| 維度 | DATE | DATETIME | TIMESTAMP |
|---|---|---|---|
| 顯示格式 | YYYY-MM-DD | YYYY-MM-DD HH:MM:SS | YYYY-MM-DD HH:MM:SS |
| 儲存範圍 | 1000-01-01 ~ 9999-12-31 | 1000-01-01 ~ 9999-12-31 | 1970-01-01 00:00:01 ~ 2038-01-19 03:14:07 (UTC) |
| 儲存大小 | 3 bytes | 8 bytes (5.6.4 前) / 5 bytes + 小數秒 | 4 bytes (5.6.4 前) / 4 bytes + 小數秒 |
| 時區轉換 | 無 | 無 | 寫入轉 UTC,讀取轉回會話時區 |
| 自動更新 | 不支援 | 不支援 (5.6.5 前) | 支援 DEFAULT CURRENT_TIMESTAMP / ON UPDATE CURRENT_TIMESTAMP |
| 零值處理 | 0000-00-00 | 0000-00-00 00:00:00 | 0000-00-00 00:00:00 |
| 毫秒精度 | 不支援 | 支援 (5.6.4+) 最多 6 位 | 支援 (5.6.4+) 最多 6 位 |
-- 建立測試表
CREATE TABLE tz_test (
dt DATETIME,
ts TIMESTAMP
);
-- 會話時區設為 UTC
SET time_zone = '+00:00';
INSERT INTO tz_test VALUES (NOW(), NOW());
-- 切換到 +08:00 時區
SET time_zone = '+08:00';
SELECT * FROM tz_test;
-- 結果:
-- dt: 2024-01-15 06:00:00 (不變,原樣儲存)
-- ts: 2024-01-15 14:00:00 (自動轉換為 +08:00 顯示)
陷阱:若應用部署在多時區環境,或資料庫遷移跨時區,TIMESTAMP 讀取值會隨時區變化而改變,DATETIME 保持不變。跨時區系統慎用 TIMESTAMP。
TIMESTAMP 內部用 32 位有符號整數存儲秒數,上限為 2038-01-19 03:14:07 UTC。長期運行系統(銀行、日誌、審計)必須使用 DATETIME 或 BIGINT。
CREATE TABLE auto_ts (
id INT PRIMARY KEY,
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);
-- 插入時 create_time/update_time 自動填充當前時間
-- 更新行時 update_time 自動刷新
-- DATETIME 5.6.5+ 也支援此語法
TIMESTAMP (4 bytes) 比 DATETIME (8/5 bytes) 節省一半空間,百萬級資料表可節省數十 MB。但考慮 2038 年限制,通常不建議以此為主要選型理由。
MySQL 接受寬鬆格式,但強烈建議統一使用標準格式:
'2024-01-15 14:30:45' (ISO 8601)'24-1-15' 可能被誤解析00-69 → 2000-2069,70-99 → 1970-1999'13:16:5' 會被視為錯誤,存入零值並報警告DATETIME,兼容性最好、無年份焦慮NO_ZERO_DATE,NO_ZERO_IN_DATE 禁止零值寫入DATETIME 是通用型選擇,TIMESTAMP 是特殊場景優化工具。理解時區轉換機制、2038 年限制、自動更新語法,能避開 90% 的時間型別坑。原則:業務時間用 DATETIME,系統時間戳可考慮 TIMESTAMP。