MySQL字符類型datetime與timestamp


這片博客來詳細分區一下這哥倆!

首先來說明這兩個字符類型:

DATETIME 8 1000-01-01 00:00:00 ~9999~12-31 23:59:59 0000-00-00 00:00:00
TIMESTAMP(包含時區信息) 4 1970-01-01 08:00:01~2038-01-19 11:14:07 0000-00-00  00:00:00

如上直觀的看到timestamp類型占用了更少的字節,但是timestamp表示的時間卻是有限的。

這兩個值都可以自動初始化並且更新為當前的時間戳,對於表中的任何TIMESTAMP或 DATETIME列,您可以將當前時間戳分配為默認值,自動更新值或兩者:

首先說這兩個類型都可以做的事: 這兩個類型都可以設置默認值,也都可以設置自動更新。下面舉例說明。

create table tb5(
t1 datetime default current_timestamp on update current_timestamp,     #設置為當前時間戳為默認值,並且自動更新    
t2 datetime default current_timestamp,                                 #僅設置當前時間戳為默認值
t3 timestamp default current_timestamp on update current_timestamp,
t4 timestamp default current_timestamp,
t5 varchar(10), t6
int auto_increment not null primary key)

當向表中插入一條數據時,t1~t4會插入當前時間戳的默認值!

mysql> insert into tb5(t5) select NULL;
Query OK, 1 row affected (0.05 sec)
Records: 1  Duplicates: 0  Warnings: 0

mysql> select * from tb5;  #t1~t4因為是以當前時間戳為默認值的,因此相等。
+---------------------+---------------------+---------------------+---------------------+------+----+
| t1                  | t2                  | t3                  | t4                  | t5   | t6 |
+---------------------+---------------------+---------------------+---------------------+------+----+
| 2019-01-09 13:58:10 | 2019-01-09 13:58:10 | 2019-01-09 13:58:10 | 2019-01-09 13:58:10 | NULL |  1 |
+---------------------+---------------------+---------------------+---------------------+------+----+
1 row in set (0.00 sec)

mysql>

下面我們修改插入的這一行數值,就可以發現不同了!

mysql> update tb5 set t5="a" where t6=1;
Query OK, 1 row affected (0.01 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> select * from tb5;     #看到了什么不一樣的地方。t1和t3的值會自動修改,而t2和t4的值不會的。
+---------------------+---------------------+---------------------+---------------------+------+----+
| t1                  | t2                  | t3                  | t4                  | t5   | t6 |
+---------------------+---------------------+---------------------+---------------------+------+----+
| 2019-01-09 14:00:49 | 2019-01-09 13:58:10 | 2019-01-09 14:00:49 | 2019-01-09 13:58:10 | a    |  1 |
+---------------------+---------------------+---------------------+---------------------+------+----+
1 row in set (0.00 sec)

default current_timestamp: 只是會設置字段值為當前時間戳,不會隨着記錄中其他字段的更新而更新。

on update current_timestamp: 則是表示字段值,會隨着記錄中其他字段值更新而更新為當前時間戳。

官方文檔上說timestamp默認數值為0,datetime默認值為null,但是下面語句卻執行失敗!

create table tb6(
t1 datetime on update current_timestamp,
t2 datetime not null on update current_timestamp,
t3 TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
t4 timestamp null on update current_timestamp,
t5 varchar(10),
t6 int auto_increment not null primary key
)

#錯誤提示就是Error Code: 1067. Invalid default value for 't3'

上面的t1和t3只要有對應記錄中字段數值的改變那么t1和t3的值就會更新。如果想不讓他們自動自動更新,除了修改其默認屬性(也就是不添加on update current_timestamp)外,MySQL還有一個變量控制這個行為:explicit_defaults_for_timestamp,其默認值為

mysql> show variables like "%explicit%";
+---------------------------------+-------+
| Variable_name                   | Value |
+---------------------------------+-------+
| explicit_defaults_for_timestamp | OFF   |
+---------------------------------+-------+
1 row in set (0.00 sec)

#默認數值為off,把其設置為on即可!

測試一下:

mysql> set global explicit_defaults_for_timestamp="ON";       #設置這個參數值為ON
Query OK, 0 rows affected (0.00 sec)

mysql> set session explicit_defaults_for_timestamp="ON";
Query OK, 0 rows affected (0.00 sec)

mysql> show variables like "%explicit%";       
+---------------------------------+-------+
| Variable_name                   | Value |
+---------------------------------+-------+
| explicit_defaults_for_timestamp | ON    |
+---------------------------------+-------+
1 row in set (0.01 sec)

mysql> insert into tb5(t5) select NULL;              #插入數據,
Query OK, 1 row affected (0.00 sec)
Records: 1  Duplicates: 0  Warnings: 0

mysql> select * from tb5;                            #查看其第二行的數據
+---------------------+---------------------+---------------------+---------------------+------+----+
| t1                  | t2                  | t3                  | t4                  | t5   | t6 |
+---------------------+---------------------+---------------------+---------------------+------+----+
| 2019-01-09 14:00:49 | 2019-01-09 13:58:10 | 2019-01-09 14:00:49 | 2019-01-09 13:58:10 | a    |  1 |
| 2019-01-09 14:44:08 | 2019-01-09 14:44:08 | 2019-01-09 14:44:08 | 2019-01-09 14:44:08 | NULL |  2 |
+---------------------+---------------------+---------------------+---------------------+------+----+
2 rows in set (0.00 sec)

mysql> update tb5 set t5="b" where t6=2;              #更改第二行的字段值
Query OK, 1 row affected (0.01 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> select * from tb5;                             #可以看到t1和t3的值還是自動更新了
+---------------------+---------------------+---------------------+---------------------+------+----+
| t1                  | t2                  | t3                  | t4                  | t5   | t6 |
+---------------------+---------------------+---------------------+---------------------+------+----+
| 2019-01-09 14:00:49 | 2019-01-09 13:58:10 | 2019-01-09 14:00:49 | 2019-01-09 13:58:10 | a    |  1 |
| 2019-01-09 14:44:41 | 2019-01-09 14:44:08 | 2019-01-09 14:44:41 | 2019-01-09 14:44:08 | b    |  2 |
+---------------------+---------------------+---------------------+---------------------+------+----+
2 rows in set (0.00 sec)

原因是什么?explicit_defaults_for_timestamp的數值會影響表結構,當表結構已經創建,那么再設置這個數值是不會起作用的。並且在定義的時候不需要顯示指定on update current_timestamp參數。

可以參考這片博客:https://www.cnblogs.com/JiangLe/p/6956865.html

二者的不同

上面提到的都是這兩個類型都可以做的事,下面來說明二者的不同之處。

1:上面已經提到的二者占用的大小不同,datetime占用8個字節,而timestamp占用4個字節。

2:還有就是表示的時間范圍不同。

3:timestamp的時間顯示值依賴於時區;如果在多個時區存儲或訪問數據,timestamp和datetime的行為將很不一樣。timestamp提供的數值和時區有關系,而datetime則是文本表示的日期和時間。

除了特殊的行為,通常也應該盡量使用TIMESTAMP。

如果要存儲比秒更小粒度的日期和時間怎么辦?MySQL目前沒有提供合適的數據類型,但是可以使用自己的存儲格式;可以使用BIGINT類型存儲微妙級別的問題,或者使用DOUBLE存儲秒之后的小數部分。也可以使用mariadb或者percona server。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM