1.概述
在我們設計表的時候,考慮將行數據的創建時間和最后更新時間記錄下來是很好的實踐。尤其是可能需要做數據同步或者對數據新鮮度有要求的表。舉些應用場景,更新距上次更新超過2小時的行數據,或者是將一個月前的訂單數據歸檔等等。我們想把這個的需求丟給數據庫服務器管理,而不是在應用程序中對每一條語句設置創建時間和最后更新時間字段。在mysql中,這實現起來很容易。我們需要借助於DEFAULT CURRENT_TIMESTAMP 和 ON UPDATE CURRENT_TIMESTAMP
2.簡單示例
1 --創建測試表 2 CREATE TABLE `timestampTest` ( 3 `id` int(11) NOT NULL AUTO_INCREMENT, 4 `name` varchar(20) DEFAULT NULL, 5 `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, 6 `last_modify_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, 7 PRIMARY KEY (`id`) 8 ) ENGINE=InnoDB DEFAULT CHARSET=utf8 9 10 --檢測默認值,插入測試數據 11 INSERT INTO timestampTest (name) VALUES ('aa'),('bb'),('cc'); 12 13 --檢測自動更新,更新某條數據 14 UPDATE timestampTest SET name = 'ab' WHERE id = 1;
例子非常簡單,結果也很明顯,我就不加贅述了。
3.思考
-
執行update語句,並未改變列值(或者說設置值為當前值),on update current_timestamp列是否會更新?
不會,大家可以看一下執行完update后出現的提示——Rows matched: 1 Changed: 0 Warnings: 0。官方文檔的解釋是
An auto-updated column remains unchanged if all other columns are set to their current values. To prevent an auto-updated column from updating when other columns change, explicitly set it to its current value. To update an auto-updated column even when other columns do not change, explicitly set it to the value it should have
-
CURRENT_TIMESTAMP,CURRENT_TIMESTAMP(),LOCALTIME,LOCALTIME(),LOCALTIMESTAMP,LOCALTIMESTAMP(),NOW()的關系?
這七個是同義詞關系
- Timestamp類型的默認值
我們討論默認情況(嚴格模式)下mysql對timestamp類型的處理:
- mysql不會給timestamp設置默認值,除非顯式設置default約束或者可空null。特例:mysql會給表第一個timestamp類型的字段同時添加default current_timestamp和on update timestamp
- 禁止mysql的特例處理有兩個辦法
- 設置
explicit_defaults_for_timestamp
為enable - 顯式設置該字段default或者null
- timestamp列默認not null。沒有顯式指定nullable,那么default null不合法
- 其他情況均會引起不合法報錯
舉一些例子,幫助理解
1 #語句不合法,出現了兩個未顯示設置default或null的timestamp 2 CREATE TABLE `tt1` ( 3 `id` int(11) NOT NULL AUTO_INCREMENT, 4 `name` varchar(20), 5 `t1` timestamp , 6 `t2` timestamp , 7 PRIMARY KEY (`id`) 8 ) ENGINE=InnoDB DEFAULT CHARSET=utf8 9 10 #語句合法,t1字段 not null default current_timestamp on update current_timestamp,t2可空 11 CREATE TABLE `tt2` ( 12 `id` int(11) NOT NULL AUTO_INCREMENT, 13 `name` varchar(20), 14 `t1` timestamp , 15 `t2` timestamp null, 16 PRIMARY KEY (`id`) 17 ) ENGINE=InnoDB DEFAULT CHARSET=utf8 18 19 #語句不合法 t2字段沒有設置default或null,也非表的第一個timestamp字段 20 CREATE TABLE `tt3` ( 21 `id` int(11) NOT NULL AUTO_INCREMENT, 22 `name` varchar(20), 23 `t1` timestamp null, 24 `t2` timestamp , 25 PRIMARY KEY (`id`) 26 ) ENGINE=InnoDB DEFAULT CHARSET=utf8 27 28 #語句不合法,這個看起來貌似合法,套用我們的規則,可以發現t2字段沒有顯示指定null/default,盡管指定了not null也不行 29 CREATE TABLE `tt4` ( 30 `id` int(11) NOT NULL AUTO_INCREMENT, 31 `name` varchar(20), 32 `t1` timestamp null, 33 `t2` timestamp not null, 34 PRIMARY KEY (`id`) 35 ) ENGINE=InnoDB DEFAULT CHARSET=utf8 36 37 #語句不合法 t1,t2均合法,問題出在t3上,timestamp 默認not null,在沒有顯式指定null的時候,default null是不合法的 38 CREATE TABLE `tt5` ( 39 `id` int(11) NOT NULL AUTO_INCREMENT, 40 `name` varchar(20), 41 `t1` timestamp not null, 42 `t2` timestamp null, 43 `t3` timestamp DEFAULT null, 44 PRIMARY KEY (`id`) 45 ) ENGINE=InnoDB DEFAULT CHARSET=utf8
小技巧:可以使用show create table `tablename` 來查看mysql處理后的表定義,下面是tt2這張表的定義,驗證了我們的結論
- Timestamp和datetime的異同
timestamp | datetime | |
同 | 可自動更新和初始化,默認顯示格式相同YYYY-MM-dd HH:mm:ss | |
異 |
自動時區轉化,實際存儲毫秒數,4字節存儲 |
不支持時區,8字節存儲 |
4.參考
1.Automatic Initialization and Updating for TIMESTAMP and DATETIME