做者:魏新平,知數堂第5期MySQL實戰班學員,第10期MySQL優化班學員,現任職助教。css
MySQL的時間類型分爲DATE, DATETIME, TIMESTAMP, TIME, YEAR五個類型。接下來爲你們一一介紹下。mysql
DATE類型sql
存儲YYYY-MM-DD類型的時間,取值範圍是'1000-01-01' to '9999-12-31'。數據庫
DATETIME和TIMESTAMP類型微信
兩個類型都是用來存儲YYYY-MM-DD hh:mm:ss[.fraction]格式的時間。不過在取值範圍和存儲方式上有些不一樣。優化
取值範圍code
DATETIME的取值範圍是'1000-01-01 00:00:00' 到 '9999-12-31 23:59:59', TIMESTAMP的取值範圍是'1970-01-01 00:00:01' UTC to '2038-01-19 03:14:07' UTC。能夠看出來DATETIME的取值範圍大不少。ip
存儲方式ci
DATETIME是直接存儲插入的時間。而TIMESTAMP是將插入的值轉換爲utc時間,而後存入數據庫,取出來的時候再根據當前會話的時區進行轉換顯示。文檔
admin@localhost [weixinpingtest] 10:05:51>create table testtime(a timestamp,b datetime); Query OK, 0 rows affected (0.05 sec) admin@localhost [weixinpingtest] 10:07:20>insert into testtime() values(now(),now()); Query OK, 1 row affected (0.01 sec) admin@localhost [weixinpingtest] 10:07:37>select * from testtime; +---------------------+---------------------+ | a | b | +---------------------+---------------------+ | 2020-03-04 10:07:37 | 2020-03-04 10:07:37 | +---------------------+---------------------+ 1 row in set (0.00 sec) admin@localhost [weixinpingtest] 10:07:43>set timezone = '+9:00';#修改時區之後,下面顯示的時間就不同了 Query OK, 0 rows affected (0.00 sec) admin@localhost [weixinpingtest] 10:07:50>select * from testtime; +---------------------+---------------------+ | a | b | +---------------------+---------------------+ | 2020-03-04 11:07:37 | 2020-03-04 10:07:37 | +---------------------+---------------------+ 1 row in set (0.00 sec)
能夠看到只要修改時區,第二次查詢的時候,timestamp類型的字段時間多了一個小時,而datetime類型的字段時間沒有變化。
自動初始化和更新
雖然有點廢話,可是仍是要介紹一下這兩個功能究竟是什麼做用。
自動初始化的關鍵字是DEFAULT CURRENT_TIMESTAMP。
CREATE TABLE t1 ( a int, ts TIMESTAMP DEFAULT CURRENT_TIMESTAMP , )
當往表t1中插入數據時,若是沒有指定ts的值,那麼ts會被設置爲當前時間。
自動更新的關鍵字是ON UPDATE CURRENT_TIMESTAMP
CREATE TABLE t1 ( a int, ts TIMESTAMP ON UPDATE CURRENT_TIMESTAMP );
當表t1的a字段更新時,ts會自動更新到修改的時間。可是若是a修改的時候值沒有變化,那麼ts也不會變化。
DEFAULT CURRENT_TIMESTAMP和ON UPDATE CURRENT_TIMESTAMP能夠同時指定,或者只指定其中一個。二者的前後順序不會有什麼影響。
explicit_defaults_for_timestamp變量
針對timestamp還有一個數據庫變量。explicit_defaults_for_timestamp。 這個變量默認是off的。那麼off的時候會有什麼現象呢。
admin@localhost [weixinpingtest] 10:07:52>show global variables like '%explicitdefaultsfortimestamp%'; +---------------------------------+-------+ | Variablename | Value | +---------------------------------+-------+ | explicitdefaultsfortimestamp | OFF | +---------------------------------+-------+ 1 row in set (0.00 sec) admin@localhost [weixinpingtest] 10:15:14>create table testt3(a timestamp,b timestamp); Query OK, 0 rows affected (0.02 sec) admin@localhost [weixinpingtest] 10:15:44>show create table testt3; +---------+------------------------------------------------------------------------------+ | Table | Create Table +---------+------------------------------------------------------------------------------+ | testt3 | CREATE TABLE test_t3 (a timestamp NOT NULL DEFAULT CURRENTTIMESTAMP ON UPDATE CURRENT_TIMESTAMP,b timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 | 1 row in set (0.00 sec)
有兩種方法能夠阻止這種現象的發生,第一個是直接設定explicit_defaults_for_timestamp參數爲on,第二個是給字段設置默認值,或者直接設置能夠爲能夠爲null。
admin@localhost [weixinpingtest] 10:21:47>show create table testt4; +---------+--------------------------------------------+ | Table | Create Table | +---------+-------------------------------------------+ | test_t4 | CREATE TABLE test_t4 (a timestamp NULL DEFAULT NULL,b timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 | +---------+-------------------------------------------+ 1 row in set (0.00 sec) admin@localhost [weixinpingtest] 10:21:54>insert into testt4() values(null,null); Query OK, 1 row affected (0.01 sec) admin@localhost [weixinpingtest] 10:22:03>select * from testt4; +------+---------------------+ | a | b | +------+---------------------+ | NULL | 2020-03-05 10:22:03 | +------+---------------------+ 1 row in set (0.00 sec) admin@localhost [weixinpingtest] 10:22:12>set explicitdefaultsfortimestamp=on; Query OK, 0 rows affected (0.00 sec) admin@localhost [weixinpingtest] 10:25:11>insert into testt4() values(null,null); ERROR 1048 (23000): Column 'b' cannot be null
test_t4表當中a字段能夠爲null,b字段默認,不能爲null,可是插入null值都沒有報錯,只不過a字段變成了null,b字段變成了當前時間。後面我開啓了explicit_defaults_for_timestamp,再次插入null,就報錯,說b不能爲null了。
至於要不要開啓這個變量就看你本身了,反正是能夠在線關閉和開啓的。
秒後面的小數
DATETIME和TIMESTAMP都是能夠在定義字段類型時加上(n),好比DATETIME(3),這裏的3表示秒後面的小數能夠精確到幾位。n的取值範圍是0-6。若是不設定,默認是0。須要注意的是,當指定了初始化和自動更新時,後面的也要加上這個數字。並且必須保持一致。以下
admin@localhost [weixinpingtest] 10:34:53>CREATE TABLE testt5( ts TIMESTAMP(6) DEFAULT CURRENTTIMESTAMP(6) ON UPDATE CURRENTTIMESTAMP(6) ); Query OK, 0 rows affected (0.01 sec) admin@localhost [weixinpingtest] 10:35:29>CREATE TABLE testt5( ts TIMESTAMP(6) DEFAULT CURRENTTIMESTAMP(6) ON UPDATE CURRENTTIMESTAMP(3) ); ERROR 1294 (HY000): Invalid ON UPDATE clause for 'ts' column
若是不一致就會報錯。
TIME類型
存儲hh:mm:ss類型的數據,取值範圍是'-838:59:59.000000' to '838:59:59.000000'。範圍能夠取這麼大的緣由是time還能夠表示時間差,因此範圍會大於24個小時,甚至是負數。TIME也是支持秒的小數的。
YEAR類型
存儲年份的。取值範圍是1901 - 2155 和 0000。
tips
針對DATE和DATETIME,表示的範圍很是大,可是mysql有一句提示語。For the DATE and DATETIME range descriptions, 「supported」 means that although earlier values might work, there is no guarantee.表示雖然支持那麼大的時間範圍,可是我不保證這個能行。
我的微信:lvqingshan_