兩類型顯示格式相同(YYYY-MM-DD HH:MM:SS),但底層機制截然不同。選錯類型會導致跨時區資料錯誤、年份溢位或預設值行為不符預期。
| 特性 | DATETIME | TIMESTAMP |
|---|---|---|
| 儲存大小 | 8 Bytes | 4 Bytes |
| 支援範圍 | 1000-01-01 ~ 9999-12-31 | 1970-01-01 00:00:01 UTC ~ 2038-01-19 03:14:07 UTC |
| 儲存方式 | 字面值(YYYY-MM-DD HH:MM:SS) | Unix Timestamp(UTC 秒數) |
| 時區轉換 | 無,存什麼讀什麼 | 有,寫入轉 UTC,讀出轉回 Session 時區 |
| 預設值 | 可設 NULL 或固定值 | 預設 NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP |
| 年份 2038 問題 | 無 | 有(32 位元秒數上限) |
舊版支援 TIMESTAMP(14)、TIMESTAMP(8) 等顯示寬度,MySQL 8.0 已移除,統一完整顯示。
TIMESTAMPDATETIMECREATE TABLE `t` (
`created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);
避免 字串直接比較:
-- 避免
WHERE `dt` > '2023-01-01 12:00:00'
推薦 使用函數明確轉換:
-- 方法 1:UNIX_TIMESTAMP(明確秒數比較)
WHERE UNIX_TIMESTAMP(`dt`) > UNIX_TIMESTAMP('2023-01-01 12:00:00')
-- 方法 2:BETWEEN(利用索引範圍掃描)
WHERE `dt` BETWEEN '2023-01-01 12:00:00' AND '2023-01-01 13:00:00'
-- 方法 3:DATE() 擷取日期部分(會失效索引,慎用)
WHERE DATE(`dt`) = '2023-01-01'
DATETIME 支援 DEFAULT CURRENT_TIMESTAMP 及 ON UPDATETIMESTAMP(N) 顯示寬度語法理解儲存機制與時區行為,才能在分散式系統中正確處理時間資料。