1. 程式人生 > >面試題:能談談Date、Datetime、Time、Timestamp、year的區別嗎?

面試題:能談談Date、Datetime、Time、Timestamp、year的區別嗎?

#### 一、 推薦閱讀 首發地址:https://mp.weixin.qq.com/s/9zKX86P4kzlKla6-NyS3EA

使用推薦閱讀,有更好的閱讀體驗
#### 二、準備 如果面試官問你:瞭解 date、datetime、time、timestamp、year 有什麼區別嗎? 其實大概率就是看你曾經用過哪些,以及有沒有留心對比它們的異同。如果你沒有時間去做一下小實驗,沒關係!大概瀏覽一下我下面的小Case就OK了。 建立下面這張表,下面的 insert sql 都是往這個表中插入資料。 ![](https://img2020.cnblogs.com/blog/1496926/202011/1496926-20201113094748206-177525150.png) #### 三、Year 支援範圍:1901~2155 。 > 1901那年清政府簽訂了《辛丑條約》 在 MySQL5.7.5 中刪除了對Year(2)的支援,同一轉換為Year(4)。所以如果你使用這個版本的MySQL,會發現它會把年份以4位長度的數字展示給我們看。 你可以嘗試插入一個超過它規定的上限2155的值 -- 2156 ,如下: ![](https://img2020.cnblogs.com/blog/1496926/202011/1496926-20201113094748740-1791323369.png) 你會發現MySQL報錯了,這是因為預設情況下MySQL開啟了嚴格模式! 針對非法值的插入,MySQL是否報錯取決於SQL是否開啟了嚴格模式。 > 白日夢在上一篇“ 對NotNull欄位插入Null值有什麼現象” 中跟大家提及到了 什麼是 sql mode,並且說了幾個和日期相關的sql mode。不記得的同學可以去看一下。 比如通過下面的命令關閉嚴格模式。 ![](https://img2020.cnblogs.com/blog/1496926/202011/1496926-20201113094749591-1771915177.png) 然後插入非法值,結果很明顯,不會報錯。而且MySQL幫你插入了0值。 ![](https://img2020.cnblogs.com/blog/1496926/202011/1496926-20201113094750140-109556628.png) #### 四、Date 支援的範圍:1000-01-01 ~ 9999-12-31 下面做幾個插入的小實驗 ![](https://img2020.cnblogs.com/blog/1496926/202011/1496926-20201113094751082-222597266.png) 看上面的例子,使用MySQL5.7預設的情況下是可以插入比1000-01-01更早的時間的! 那能不能插入0000-00-00呢?這取決於你使用的那種sql mode! 預設情況下是插入不進去的,如下: ![](https://img2020.cnblogs.com/blog/1496926/202011/1496926-20201113094751730-697981118.png) 插不進去的原因是:mysql5.7 預設的sql mode中開啟了嚴格模式。 且開啟使用了引數`NO_ZERO_DATE`。 這個引數與嚴格模式一起起作用就會導致不能插入 0-0-0。 如果偏偏想插入 0-0-0 可以像下面這樣將其去掉,然後重試。 ![](https://img2020.cnblogs.com/blog/1496926/202011/1496926-20201113094752251-1860429562.png) #### 五、Datetime 支援範圍:1000-01-01 00:00:00.000000 to 9999-12-31 23:59:59.999999 很明顯,Datetime比Date更精確。 ![](https://img2020.cnblogs.com/blog/1496926/202011/1496926-20201113094752945-154386706.png) 不允許插入數字格式的日期。 #### 六、Time 支援範圍:-838:59:59.000000 to 838:59:59.000000 time型別不僅可以用來表示24h,還可以用來表示一個時間範圍,這個時間範圍可能會很大,甚至是負的。 下面做幾個小實驗 ![](https://img2020.cnblogs.com/blog/1496926/202011/1496926-20201113094753544-1378384495.png) 秒數是滿60進1的。 所以我插入60時,在jdbc層面會爆出下面的錯誤:format exception ![](https://img2020.cnblogs.com/blog/1496926/202011/1496926-20201113094754014-1936176902.png) --- 可以插入正常的時間 ![](https://img2020.cnblogs.com/blog/1496926/202011/1496926-20201113094754353-1293192192.png) **在看下面這個例子:** 雖然mysql支援往time字中插入`-838:59:59.000000` 但是失敗了。 ![](https://img2020.cnblogs.com/blog/1496926/202011/1496926-20201113094755007-311050232.png) 原因如下圖: IDE本身通過java的jdbc驅動連線MySQL。 jdbc嘗試會將`-838:59:59.000000` 轉換成Java的封裝類,結果還轉失敗了。 ![](https://img2020.cnblogs.com/blog/1496926/202011/1496926-20201113094755505-912087703.png) 在直接連線MySQL是不會出現上圖這種情況的。 ![](https://img2020.cnblogs.com/blog/1496926/202011/1496926-20201113094756077-1927135474.png) > 如果範圍超過了 -838:59:59.000000 to 838:59:59.000000 這兩個邊界值 ,就插入這邊界值。 接著再看幾個典型的例子: ![](https://img2020.cnblogs.com/blog/1496926/202011/1496926-20201113094756488-1392171400.png) #### 七、Timestamp 支援範圍: 1970-01-01 00:00:01 UTC to 2038-01-19 03:14:07 UTC > 因為32位能表示的最大值是2147483647。另外1年365天的總秒數是 31536000,2147483647/31536000 = 68.1,也就是說32位能表示的最長時間是68年,從1970年開始的話,加上68.1,實際最終到2038年01月19日03時14分07秒。 > > 過了這個上線,所有32位作業系統時間都會變成10000000 00000000 00000000 00000000 > > 這個問題在64位作業系統中已經不復存在 好,開始我們的實驗! 先嚐試插入幾個零值,無一例外,全部報錯失敗。 ![](https://img2020.cnblogs.com/blog/1496926/202011/1496926-20201113094757134-434149454.png) 再插入一些大點的值 ![](https://img2020.cnblogs.com/blog/1496926/202011/1496926-20201113094757720-1034373660.png) 你會不會詫異這樣一個問題: timestamp合法區間最小值不是1970-01-01 00:00:01嗎? 那為什麼在上面的例子中我嘗試寫入插入1970-01-01 00:00:01竟然會失敗? 那是因為我機器上的MySQL使用的時區是CST:China Standard Time UT+8:00 以北京時間為準,我們是在東八區。所以最後是+8:00 , 而不是+0:00 ![](https://img2020.cnblogs.com/blog/1496926/202011/1496926-20201113094758236-88407996.png) 所以如果我們在1970-0101-000001後順延八個小時,就能插入成功! ![](https://img2020.cnblogs.com/blog/1496926/202011/1496926-20201113094758608-875177653.png) 補充: | 列型別 | 顯示格式 | | ------------- | -------------- | | TIMESTAMP(14) | YYYYMMDDHHMMSS | | TIMESTAMP(12) | YYMMDDHHMMSS | | TIMESTAMP(10) | YYMMDDHHMM | | TIMESTAMP(8) | YYYYMMDD | | TIMESTAMP(6) | YYMMDD | | TIMESTAMP(4) | YYMM | | TIMESTAMP(2) | YY | #### 八、預設值 在你建立表的時候,可以為你的時間列選定一個預設值。 ![](https://img2020.cnblogs.com/blog/1496926/202011/1496926-20201113094759278-385071964.png)
#### 九、關注

為大家帶來MySQL面試專題!本文是第 4 篇、全文110篇!公眾號首發!

以問答的方式,由淺入深的幫你應對各類MySQL面試題的狂轟濫炸!當然也不乏會分享一些高階讀寫分離資料庫中介軟體原理及落地的技術實現,為你揭開資料庫中介軟體神祕的面紗!

面試官都關注了!你還在猶豫什麼呢? ![image-20201111055731223](https://img2020.cnblogs.com/blog/1496926/202011/1496926-20201113094800860-1529321582.png)