日期時間類型中包含如下幾種數據類型:html
各種型都有具體的取值範圍,超出或非法的其餘值時,MySQL 會回退到 0。TIMESTAMP 類型是個例外,給它設置一個超出範圍的值時,將保存上該類型容許的最大值。mysql MySQL 按標準格式 YYYY-MM-DD hh:mm:ss[.fraction] 輸出日期時間,但設置或進行日期時間相關的比較時卻支持靈活的多種格式,會自動解析。具體支持的輸入格式可參見 Section 9.1.3, 「Date and Time Literals」。其中 fraction 部分爲秒後面的小數部分,取值範圍爲 0~6 位。sql 雖然 MySQL 支持多種格式進行日期時間的設置,但日期部分要求必須是 年-月-日 的形式才能正確解析。好比 98-09-04 是按年月日順序解析的,而不是英文裏經常使用的月日年,或者日月年。shell 年在只給了兩位數的狀況下,MySQL 嘗試使用如下規則來補全:服務器
- 給定的兩位數爲 70~99 時解析成 1970 ~ 1999。
- 給定爲 00 ~ 69 時解析成 2000 ~ 2069。
因此,爲了不不可預測的結果,使用時仍是指定全一些。函數
- 在須要使用數字的語境下,MySQL 會將日期時間自動轉成數字。同理,在須要日期時間的相關操做語境下,會嘗試將數字解析成日期時間。
- 經過設置 MySQL 相關參數,日期類型可保存本來非法的值,好比開啓 ALLOW_INVALID_DATES 設置項時,可設置日期類型保存一個
2009-11-31 值,但正常狀況下咱們知道 11 月哪來什麼 31 號。此時 MySQL 僅僅只是不檢查月分與日期的關聯性,但月分的取值範圍 112 及日期的取值範圍 131 仍是要單獨各自作校驗的。
mysql> INSERT INTO todo (title,created_on) VALUES ('blah','2019-09-31');
ERROR 1292 (22007): Incorrect date value: '2019-09-31' for column 'created_on' at row 1
mysql> SET SESSION sql_mode = 'ALLOW_INVALID_DATES';
Query OK, 0 rows affected (0.00 sec)
mysql> INSERT INTO todo (title,created_on) VALUES ('blah','2019-09-31');
Query OK, 1 row affected, 1 warning (0.01 sec)
mysql> SELECT * FROM todo;
+----+------+------------+
| id | title | created_on |
+----+------+------------+
| 1 | blah | 2019-09-31 |
+----+------+------------+
1 rows in set (0.00 sec)
某些場景下你可能須要保存部分日期,好比用戶只輸入了年沒輸入月日。因此 MySQL 是支持將月日設置成 0,好比 2019-00-00 。但這種狀況下就沒法從日期相關的操做中得到到準確的結果,好比使用 DATE_SUB() 或 DATE_ADD() 函數時。禁用月日的零值可經過開啓 MySQL 的 NO_ZERO_IN_DATE 模式。spa 除了月日可零,MySQL 還支持設置年月日都零的值 0000-00-00 ,對於日期非必填的狀況比較有用,由於此時它比單純的 NULL 更有語義。可經過開啓 MySQL 的 NO_ZERO_DATE 模式來禁用這個全零的值。code 各日期時間零值格式以下,但實際時用時,直接簡寫成一個 0 效果是等效的。server
Data Type |
「Zero」 Value |
DATE |
'0000-00-00' |
TIME |
'00:00:00' |
DATETIME |
'0000-00-00 00:00:00' |
TIMESTAMP |
'0000-00-00 00:00:00' |
YEAR |
0000 |
DATE,DATETIME,及 TIMESTAMP 三者具備相關性,都支持多種格式的自動解析,詳見 Date and Time Literals。htm DATE 日期格式不帶時間 TIME 部分,查詢時輸出格式爲 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 同 DATETIME ,但取值範圍基於 UTC 時間,較 DATETIME 要小,爲 1970-01-01 00:00:01 UTC 到 2038-01-19 03:14:07 UTC。因此使用 TIMESTAMP 格式的時間,到 2038 年會溢出,這就是 Year 2038 problem。關於該問題的討論和解決可參見這個 StackOverflow 的回答。 既然如此,爲什麼要使用這個取值範圍更小的呢。TIMESTAMP 存儲的值是帶時區的。在存儲時會根據當前時區轉成 UTC(universal time zone) 存儲,查詢時也會根據時區從 UTC 轉換到具體的時間。對於支持多語及國際化全球部署的應用來講,顯得尤其方便。須要注意的是,這裏操做基於的時區默認爲服務器的時區,可經過改變 time_zone SET GLOBAL time_zone=time_zone 來修改。時區的設置也能夠是以鏈接爲單位,這樣來自不一樣時區的請求可獲得不一樣的時間。 TIMESTAMP 和 DATETIME 均可包含至多 6 位的小數來表示時間中毫秒(microseconds)的部分。因此,帶上毫秒時完整的格式是 YYYY-MM-DD hh:mm:ss[.fraction] 。前者取值範圍爲 1970-01-01 00:00:01.000000 到 2038-01-19 03:14:07.999999 ,後者爲 1000-01-01 00:00:00.000000 到 9999-12-31 23:59:59.999999 。 在寫入時,對於非法的日期時間值,將自動存成零值,即 '0000-00-00' 或 '0000-00-00 00:00:00'。 關於日期時間須要注意的點:
- 由於 MySQL 支持比較寬鬆的格式來設置日期時間,因此理論上你能夠用你想用的值來作爲數字之間的分界符,但使用時須要關注其解析的原理。好比給一個日期格式的列設置
10:11:12 ,雖然這個值看起來像時間類型,但仍是能夠正確在被解析成目標列的格式,即日期。若是這這個日期列設置 10:45:15 則會認爲是非法值,由於 45 不是一個合法的月份值,因此存儲時變成零值 0000-00-00 。
- 日期時間與毫秒的分界符必需是小數點。
- 默認 MySQL 除了檢查日月值是否有有效範圍 1~ 31,1~12。還會將二者結合進來檢查,好比 4 月沒有 31。因此對於日期
2004-04-31 算是非法的,會變成零值 0000-00-00 。若是不須要這樣的約束檢查,可開啓 MySQL 的 ALLOW_INVALID_DATES 模式。
日期時間的自動初始化及更新 TIMESTAMP 和 DATETIME 還支持自動初始化(auto-initialized)和更新到當前時間(auto-updated)。
- 建立表定義列時,指定
DEFAULT CURRENT_TIMESTAMP 來使相應的日期時間列自動初始化。
- 指定
ON UPDATE CURRENT_TIMESTAMP 來使相應的日期時間列自動更新。
二者可同時做用於一個日期時間列,表示插入記錄時自動初始化成當前時間,後續記錄更新時自動更新到當前時間。 其中 CURRENT_TIMESTAMP 指代當前時間,與其有相同效果的還有 CURRENT_TIMESTAMP() , NOW() , LOCALTIME , LOCALTIME() , LOCALTIMESTAMP 以及 LOCALTIMESTAMP() 。 DEFAULT 除了可指定成當前時間外,也可指定一個任意的固定值,好比 DEFAULT 0 或 `DEFAULT '2000-01-01 00:00:00'。 對於指定了自動初始化的列,插入時若是沒指定該列的值,則會自動設置爲當前的時間。 對於指定爲自動更新的列,一旦一條記錄中有字段變動,該日期會自動更新成變動時的時間。若是不想它更新,可在插入其餘值時手動設置一下該日期列爲原有的值,讓其保持不變。 TIMESTAMP 和 DATETIME 在列的定義時,若是指定了小數部分,那麼在配合使用 CURRENT_TIMESTAMP(fsp) 時,這個小數部分的精度須要保持一致。好比:
-- ✅
CREATE TABLE t1 (
ts TIMESTAMP(6) DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6)
);
-- 🚨
CREATE TABLE t1 (
ts TIMESTAMP(6) DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP(3)
);
TIME 時間 TIME 格式即日期時間中時間的部分,輸出格式爲 hh:mm:ss 或時間較大時爲 hhh:mm:ss ,取值範圍 -838:59:59 到 838:59:59 。一樣地,也是支持帶至多 6 位小數表示毫秒。 設置時也是支持將多種格式自動解析。對於帶冒號的狀況,好比 11:12 解析成 11:12:00 而不是 00:11:12 。不帶冒號的狀況,將最右邊的兩位數字解析成秒(按逝去的時間來解析),好比 '1112' 和 1112 不是 11:12:00 而會解析成 00:11:12 。同理,'12' 和 12 會解析成 00:00:12 。 YEAR YEAR 表示日期中年的部分,是一個 1 字節大小的類型,可經過 YEAR 或 YEAR(4) 來聲明,其展現寬度(display width)爲 4。查詢時輸出格式爲 YYYY ,取值範圍 1901 到 2155。 0000 也是合法的值。 支持使用如下格式進行設置:
- 使用 1901 ~ 2155 間的四位數字值。
- 或將上面的數字以字符串形式給定。
- 1 ~ 99 之間的數字,此時 1 ~ 69 解析成 2001 ~ 2069,70 ~ 99 解析成 1970 ~ 1999.
- 其餘可返回合法值的方法,好比
NOW() 。
相關資源
|