在 MySQL 中向 DATE 類型字段插入數據時,使用 CURDATE() - 5 這類日期運算,卻拋出錯誤:
ERROR 1292 (22007): Incorrect date value: '20160398' for column 'addtime' at row 1
乍看之下 CURDATE() 返回日期,減去整數應當合法,為何會生成 20160398 這樣非法日期?
CURDATE() 在字符串上下文返回 'YYYY-MM-DD' 格式,在數值上下文返回 YYYYMMDD 格式的整數(如 20160303)。
當執行 CURDATE() - 5 時,MySQL 將 CURDATE() 視為數值上下文,得到整數 20160303,減 5 變成 20160298(注意:這是直接數學減法,非日期運算!)。隨後插入 DATE 列,MySQL 嘗試將 20160298 解析為日期,格式為 YYYYMMDD,但 98 非法(月份最大 12,日期最大 31),故報錯 20160398(錯誤信息中月份日份可能因版本差異顯示不同,本質相同)。
-- 正確:日期運算函數
INSERT INTO item (..., addtime, endtime, ...)
VALUES (..., DATE_SUB(CURDATE(), INTERVAL 5 DAY), DATE_ADD(CURDATE(), INTERVAL 30 DAY), ...);
DATE_SUB()、DATE_ADD() 專為日期運算設計,自動處理月份翻轉、閏年等邊界情況,返回標準 DATE 類型,安全可靠。
-- 利用 CONCAT() 或 CAST() 強制字符串模式
INSERT INTO item (..., addtime, ...)
VALUES (..., DATE(CONCAT(CURDATE(), ' -5 DAY')), ...); -- 不推薦,繁瑣且易錯
在 Java、Python 等應用代碼中用 LocalDate、datetime 計算好具體日期字符串 '2016-02-27' 傳給 SQL,徹底避開 MySQL 日期運算陷阱,也是生產環境最佳實踐。
| 錯誤寫法 | 問題本質 | 正確替代 |
|---|---|---|
CURDATE() - 5 | 數值減法產生非法整數 | DATE_SUB(CURDATE(), INTERVAL 5 DAY) |
CURDATE() + 30 | 同理,數值加法 | DATE_ADD(CURDATE(), INTERVAL 30 DAY) |
CURDATE() - INTERVAL 5 DAY | 語法錯誤,- 不支持 INTERVAL | DATE_SUB(CURDATE(), INTERVAL 5 DAY) |
核心原則:凡是涉及日期加減,請無腦使用 DATE_ADD() / DATE_SUB() 或應用層計算,切勿直接用 +/- 操作符。