當我在MySQL
數據庫中嘗試插入一條帶有時間戳的數據時報錯:html
mysql> insert into alarm_service values (6, '1970-01-01 08:00:00'); ERROR 1292 (22007): Incorrect datetime value: '1970-01-01 08:00:00' for column 'time' at row 1 # 查看錶結構 mysql> show create table alarm_service; +---------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | Table | Create Table | +---------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | alarm_service | CREATE TABLE `alarm_service` ( `id` int(11) NOT NULL AUTO_INCREMENT, `time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8 | +---------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 1 row in set (0.00 sec)
咱們能夠發現錯誤信息提示是時間值錯誤,可是咱們這明顯是一個合法的時間點啊。mysql
通過查詢資料,發現緣由是在MySQL
中,timestamp
類型的合法區間是1970-01-01 00:00:01 - 2038-01-19 03:14:07 UTC
,而在存儲是,會先將你插入的數據轉換爲UTC
時間,而後存儲起來,讀取的時候,再轉換爲你的本地時間。因爲個人時區爲東八區,所以轉換後就變爲了1970-01-01 00:00:00 UTC
,成爲了非法時間。linux
解決方案爲:sql
MySQL
嚴格模式,容許非法時間下面咱們詳細說明相關的內容。數據庫
MySQL
時間類型MySQL
時間類型分爲三種:session
DATE:
用於只包含日期不包含時間的時候,MySQL
會將格式轉換爲YYYY-MM-DD
,合法範圍爲1000-01-01 - 9999-12-31
。DATETIME:
用於包含日期+
時間的時候,格式爲YYYY-MM-DD HH:MM:SS
,合法範圍爲1000-01-01 00:00:00 - 9999-12-31 23:59:59
。TIMESTAMP:
用於包含日期+
時間的時候,格式爲YYYY-MM-DD HH:MM:SS
,合法範圍爲1997-01-01 00:00:01 - 2038-01-19 03:14:07 UTC
。同時,DATETIME
和TIMESTAMP
還都支持一個6
位微秒的數據支持,格式爲YYYY-MM-DD HH:MM:SS[.fraction]
,合法範圍爲.000000 - .999999
。app
DATETIME
和TIMESTAMP
還都提供自動初始化並更新爲當前日期和時間的數據。操作系統
對於TIMESTAMP
類型,MySQL
會在存儲時將數據值轉換爲UTC
標準時間來存儲,讀取時再轉爲當前時間。若是你的時區沒有發生改變,則該值就是你存儲的值,若是你改變了時區,讀取到的值就會發生變化。這個特性不會對DATETIME
生效。code
mysql> show variables like '%zone%'; +------------------+--------+ | Variable_name | Value | +------------------+--------+ | system_time_zone | CST | | time_zone | SYSTEM | +------------------+--------+
能夠看到當前設置的時區是SYSTEM
,即跟操做系統保持一致,同時系統的時區是CST(China Standard Time 北京標準時間)
,查看系統時間也能夠看到是東8區(+0800)
:htm
$ date -R Tue, 23 Apr 2019 11:22:47 +0800
所以咱們輸入1970-01-01 08:00:00
時MySQL會糾正爲1970-01-01 00:00:00
,而成爲一個非法值。
對於非法的時間值,針對不一樣的時間類型,MySQL
會將其轉爲合適的值:0000-00-00 或 0000-00-00 00:00:00
。
好比月份爲1-12
月,當你嘗試插入2019-13-01 00:00:00
時,就會被糾正爲0000-00-00 00:00:00
,由於不存在13
月,爲非法值。
當咱們插入非法時間值時,雖然會被糾正,可是在嚴格模式下,不會插入數據,反而會報錯:
ERROR 1292 (22007): Incorrect datetime value: '1970-01-01 08:00:00' for column 'time' at row 1
咱們能夠經過設置模式,來調整MySQL
的行爲,首先查看MySQL
的模式:
mysql> show variables like '%sql_mode%'; +----------------------------+--------------------------------------------+ | Variable_name | Value | +----------------------------+--------------------------------------------+ | | sql_mode | STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION | +----------------------------+--------------------------------------------+
在這個模式下,非法時間會直接報錯,咱們能夠調整模式爲ALLOW_INVALID_DATES
:
mysql> set session sql_mode = 'ALLOW_INVALID_DATES'; Query OK, 0 rows affected (0.00 sec) mysql> show variables like '%sql_mode%'; +---------------+---------------------+ | Variable_name | Value | +---------------+---------------------+ | sql_mode | ALLOW_INVALID_DATES | +---------------+---------------------+ 1 row in set (0.00 sec)
在這個模式下,不會再完備檢查日期的合法性,只會檢查月份的範圍在1-12
,日期在1-31
。這在處理用戶輸入的時候很合適,可是這個模式只對於DATE
和DATETIME
很合適,對於TIMESTAMP
,依然須要一個合法的值,不然就會糾正爲0000-00-00 00:00:00
。
在非法值時,若是這個模式啓用,就會報錯;若是禁用,就會糾正爲0000-00-00 00:00:00
併產生一個警告:
mysql> insert into alarm_service values (7, '1970-01-01 08:00:00'); Query OK, 1 row affected, 1 warning (0.00 sec)
對於這種問題,有兩種解決方法:
MySQL
嚴格模式,容許非法時間case
彙總ERROR 1067 (42000): Invalid default value for 'createTime'
查看緣由發現設置爲:
# 查看建立表單的語句 CREATE TABLE `dimensionsConf` ( `id` int(11) NOT NULL AUTO_INCREMENT, `createTime` datetime DEFAULT CURRENT_TIMESTAMP, ) ENGINE=InnoDB AUTO_INCREMENT=178 DEFAULT CHARSET=utf8; # 查看數據庫版本 $mysql --version mysql Ver 14.14 Distrib 5.1.30, for unknown-linux-gnu (x86_64) using EditLine wrapper
查閱官方文檔發現緣由:5.6.5
如下不支持datetime
類型,但可使用timestamp
類型。