ON UPDATE
很多人都用過,但什麼時候不觸發更新、更新有什麼壞處等細節,卻不一定都清楚。
讀完本文,您將掌握ON UPDATE
的用法、新版本特性、使用陷阱和優缺點。
自動更新效果:當數據行發生更新時,數據庫自動設置“自動更新列”的值爲當前時間1。
支持的字段類型
從MySQL 5.6.5
開始,TIMESTAMP
和DATETIME
列都支持自動更新,且一個表可設置多個自動更新列。
在MySQL 5.6.5
之前,只有TIMESTAMP
支持自動更新,且每個表只能有一個自動更新的時間列,而且不允許存在兩個列:其中一個設置了DEFAULT CURRENT_TIMESTAMP
、另一個設置了ON UPDATE CURRENT_TIMESTAMP
下面主要介紹MySQL 5.6.5
及之後版本的自動更新列用法。
語法
col DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
col TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
注意
自動更新的觸發時機
注意時間戳列“自動更新”的時機:
- 插入時如未指定該列值時。
- 當該行數據其他列有值變化時,如
update
。- 如果有更新操作、但其他列值並未變化,不會觸發。此時要更新時間戳,需在SQL中指定新值給它(例如
CURRENT_TIMESTAMP
)如
update table set column_tmt = CURRENT_TIMESTAMP
- 如果更新時不想觸發,可顯式設置時間戳列爲當前值。
如
update table set column_a = 'xxx', column_tmt = column_tmt
- 如果有更新操作、但其他列值並未變化,不會觸發。此時要更新時間戳,需在SQL中指定新值給它(例如
自動更新的時間值
CURRENT_TIMESTAMP
還可以替換爲任何等價標識符,如CURRENT_TIMESTAMP()
、NOW()
、LOCALTIME
等(所有獲取當前時間的標識符,可參考《MySQL日期與時間函數(日期/時間格式化、增減、對比、時區、UTC和UNIX時間)》)
自動更新值時,CURRENT_TIMESTAMP
表示的是SQL執行時的時間。如果要寫入實際每行數據發生變更的時間,需要執行SQL時手工設置自動更新列值爲SYSDATE()
,自動更新列的聲明中、CURRENT_TIMESTAMP()
不能替換爲SYSDATE()
。
DEFAULT
設置
DEFAULT CURRENT_TIMESTAMP
爲該列設置默認值。
DEFAULT
後的CURRENT_TIMESTAMP
可替換爲常量值,如2019-11-20 22:21:00
;
如果未設置DEFAULT
,自動更新仍然生效,只是沒有默認值而已。TIMESTAMP
的默認值爲0、除非聲明爲NULL
纔會默認NULL
,而DATETIME
默認爲NULL
、設置爲NOT NULL
時默認值爲0.
系統變量
explicit_defaults_for_timestamp
會影響默認值情況。
爲了避免一些不必要的疏忽,建議自動更新列設置DEFAULT CURRENT_TIMESTAMP
。
精度
與TIMESTAMP
/DATETIME
類型、及TIMESTAMP()
函數一樣,支持最多6位小數位。
- 各時間類型的精度,可參考《MySQL字段長度、取值範圍、存儲開銷(5.6/5.7/8.x的主要類型,區分顯示寬度/有無符號/定點浮點、不同時間類型)》中的“日期與時間”部分
- 時間函數相關,可參考《MySQL日期與時間函數(日期/時間格式化、增減、對比、時區、UTC和UNIX時間)》)
設置小數位時,各部分的精度必需保持一致,如:
col DATETIME(6) DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6)
如果精度不一致、或部分設置了精度部分未設置,會報錯ERROR 1067 (42000): Invalid default value for 'tmt'
。
總結
自動更新列有好處也有不足:
好處:無需依賴業務實現時間戳,所有的db操作都會自動記錄,便於排查問題。
不足:數據庫服務器和業務服務器可能存在時間差,導致業務變動的時間與數據庫時間戳存在差異,給實際維護和使用帶來障礙。只能儘可能的校準服務器時間,但不能絕對避免該問題。
儘管如此,數據庫設計時仍建議增加一個自動更新列作爲時間戳,忠實反映數據庫的最後變化時間。