標籤:MySQL入門程序員
咱們前邊說過,MySQL
底層其實把數據存儲到了表裏邊,而表又是由行和列組成的,仍是拿咱們以前說過的學生基本信息表
作個例子:數據庫
學號 | 姓名 | 性別 | 身份證號 | 學院 | 專業 | 入學時間 |
---|---|---|---|---|---|---|
20180101 | 杜子騰 | 男 | 158177199901044792 | 計算機學院 | 計算機科學與工程 | 2018-09-01 |
20180102 | 杜琦燕 | 女 | 151008199801178529 | 計算機學院 | 計算機科學與工程 | 2018-09-01 |
20180103 | 範統 | 男 | 17156319980116959X | 計算機學院 | 軟件工程 | 2018-09-01 |
20180104 | 史珍香 | 女 | 141992199701078600 | 計算機學院 | 軟件工程 | 2018-09-01 |
20180105 | 範劍 | 男 | 181048200008156368 | 航天學院 | 飛行器設計 | 2018-09-01 |
20180106 | 朱逸羣 | 男 | 197995199801078445 | 航海學院 | 電子信息 | 2018-09-01 |
表裏的一行就表明一個學生的基本信息,這一行中的某一列就表明這個學生基本信息中的一項屬性,也就是說學號
是學生的一項屬性、姓名
也是學生的一項屬性,其餘的列也都是這個學生的屬性。可是這些屬性都有必定格式,好比說學號必須是整數格式的,入學時間必須是日期格式的,其餘的屬性都是字符串格式的,不一樣格式的數據是不能隨便亂填的,你把一個日期格式的數據填在了性別裏,豈不是鬧出了笑話。因此設計MySQL
的大叔們針對每一種格式定義了一種相應的類型,咱們接下來就要詳細嘮叨具體有哪些類型以及它們是怎麼存儲在計算機中的。bash
注:身份證號因爲最後覺得多是X,因此就歸爲字符串了。 性能
long long ago,原始人是沒有如今的人這麼聰明的,只會用十分簡單的東西計數。比方說他們只會使用麥稈來統計獵物數量,每收穫一個獵物就在麥稈堆裏添加一支麥稈,因此若是獵物多的話,麥稈就會累積不少,數都數不過來。後來人們發現不用這麼笨,能夠把麥稈摺疊成不一樣的形狀來表明不一樣的數量。普通的麥稈就表明1,也就是說每添加一隻獵物就多放一隻普通麥稈;若是當前已經放了9根普通的麥稈,此時再添加了一隻獵物,就用一個心形麥稈來取代以前的9根普通麥稈;假如當前已經有了9根心形麥稈和9根普通麥稈時又添加了一隻獵物的話,就用一根矩形麥稈來替代以前全部的麥稈。像這種每逢10個數向前進一位的計數方法就叫作十進制,這樣他們就能夠用不多的麥稈來表示很大的數字了。學習
若是在計數的時候每逢8個數就往前進一位就是八進制,每逢9個數就往前進一位就是九進制。生活中經常使用的進制除了十進制外,還有鐘錶裏用來統計時間的十二進制和六十進制,用在計算機裏的二進制和十六進制。 以十進制數字109
爲例,它表示有1個10²
,加0個10¹
,加9個10⁰
,用數學符號表示就是:優化
109 = 1 × 10² + 0 × 10¹ + 9 × 10⁰
複製代碼
這個數字也能夠這麼表示:編碼
109 = 1 × 8² + 5 × 8¹ + 5 × 8⁰
複製代碼
也就是從八進制的逢8進一的角度上考慮,這個數能夠被表示爲155
(八進制)。固然這個數也能夠這麼寫:spa
209 = 1 × 2⁶ + 1 × 2⁵ + 0 × 2⁴ + 1 × 2³ + 1 × 2² + 0 × 2¹ + 1 × 2⁰
複製代碼
也就是從二進制的逢2進一的角度上考慮,這個數也能夠被表示爲:1101101
(二進制)。又由於計算機中通常用8個位表示一個字節,平時都是用若干個字節來表示一個整數,假如用1個字節表示109
的話,那效果就是這樣:01101101
,假如用兩個字節表示十進制數19
的話,那效果就是這樣:0000000001101101
。操作系統
很顯然,使用的字節數越多,意味着能表示的數值範圍就越大,可是也就越耗費存儲空間。根據表示一個數佔用字節數的不一樣,MySQL
把整數劃分紅以下所示的類型:設計
類型 | 字節數 | 無符號數取值範圍 | 有符號數取值範圍 | 含義 |
---|---|---|---|---|
TINYINT |
1 | 0 ~ 2⁸-1 | -2⁷ ~ 2⁷-1 | 很是小的整數 |
SMALLINT |
2 | 0 ~ 2¹⁶-1 | -2¹⁶ ~ 2¹⁶-1 | 小的整數 |
MEDIUMINT |
3 | 0 ~ 2²⁴-1 | -2²⁴ ~ 2²⁴-1 | 中等大小的整數 |
INT |
4 | 0 ~ 2³²-1 | -2³² ~ 2³²-1 | 標準的整數 |
BIGINT |
8 | 0 ~ 2⁶⁴-1 | -2⁶⁴ ~ 2⁶⁴-1 | 大整數 |
以TINYINT
爲例,用1個字節,也就是8個位表示有符號數
的話,就是既能夠表示正數,也能夠表示負數的話,須要有一個二進制位表示正負號。可是若是表示無符號數
的話,也就是隻表示非負數的話,就不須要表示正負號,這是有符號數
和無符號數
的區別。具體每一個類型的取值範圍是如何計算出來的咱們這就不嘮叨了,能夠找一本計算機基礎的書看看。
浮點數就是小數,咱們平時用的的十進制小數也能夠被轉換成二進制後被計算機存儲。好比9.875
,這個小數能夠被表示成這樣:
9.875 = 8 + 1 + 0.5 + 0.25 + 0.125 = 1 × 2³ + 1 × 2⁰ + 1 × 2⁻¹ + 1 × 2⁻² + 1 × 2⁻³
複製代碼
也就是說,若是十進制小數9.875
轉換成二進制小數的話就是:1001.111
。爲了在計算機裏存儲這種二進制小數,咱們統一把它們表示成a × 2ⁿ
的科學計數法的形式,其中1≤|a|
<2,好比1001.111
能夠被表示成1.001111 × 2³
,咱們把小數點以後的001111
稱爲尾數
,把2³
中的3
稱爲指數
,而後只須要在計算機中的二進制位中表示出尾數
和指數
就好了。用科學技術法來計數的時候,小數的小數點看起來就像移動了同樣,因此這樣的小數也叫作浮點數
。
固然,若是你須要表示有符號小數
,那還得用一個二進制位來表示正負號。若是咱們用四個字節,也就是32個位來表示一個有符號小數的話,咱們能夠這麼劃分各個部分所表示的意義:
很顯然,使用的字節數越多,表示尾數
和指數
的範圍就越大,也就是說表示的小數範圍就越大,因此設計MySQL
的大叔根據表示一個小數須要的不一樣字節數定義了以下的兩種類型來表示小數:
類型 | 字節數 | 絕對值最小非0值 | 絕對值最大非0值 | 含義 |
---|---|---|---|---|
FLOAT |
4 | ±1.175494351e-38 | ±3.402823466e38 | 單精度浮點數 |
DOUBLE |
8 | ±2.2250738585072014e-308 | ±1.7976931348623157e308 | 雙精度浮點數 |
須要注意的是,雖然有的十進制小數,好比1.875
能夠被很容易的轉換成二進制數0.111
,可是更多的小數是沒法直接轉換成二進制的,好比說0.3
,它轉換成的二進制小數就是一個無限小數,可是咱們如今只能用4個字節或者8個字節來表示這個小數,因此只能進行四捨五入來近似的表示,因此咱們說計算機的浮點數表示有時是不精確的。
對於咱們用戶而言,使用的都是十進制小數。表示一個小數須要的數字個數稱爲有效位數
,小數點後的數字個數稱爲小數位數
,11.2
和-0.0021
這兩個小數的有效位數和小數位數見下表:
小數 | 有效位數 | 小數位數 |
---|---|---|
11.2 |
3 | 1 |
-0.0021 |
5 | 4 |
若是咱們知道某列屬性須要的有效位數和小數位數,咱們能夠用這樣的方式手動指定一下:
FLOAT(M, D) 或 DOUBLE(M, D),其中M指`有效位數`,D指`小數位數`
複製代碼
舉個例子看一下,設置了有效位數和小數位數的單精度浮點數的取值範圍的變化:
類型 | 取值範圍 |
---|---|
FLOAT(4, 1) |
-999.9~999.9 |
FLOAT(5, 1) |
-9999.9~9999.9 |
FLOAT(6, 1) |
-99999.9~99999.9 |
FLOAT(4, 0) |
-9999~9999 |
FLOAT(4, 1) |
-999.9~999.9 |
FLOAT(4, 2) |
-99.99~90.99 |
能夠看到,在小數位數相同的狀況下,有效位數越多,該類型的取值範圍越大;在有效位數相同的狀況下,小數位數越大,該類型的取值範圍越小。固然,M
和D
的取值也不是無限大的,你要是把有效位數取成一個億,那內存不得崩了麼,別忘了單精度浮點數只有4個字節的存儲空間,雙精度浮點數只有8個字節的存儲空間,超過了這個存儲空間所能表達的小數就無效了。
正由於用浮點數表示小數可能會有不精確的狀況,在一些狀況下咱們必須保證小數是精確的,因此設計MySQL
的大叔們提出了定點數的概念,它也是存儲小數的一種方式:
類型 | 字節數 | 取值範圍 |
---|---|---|
DECIMAL(M, D) |
取決於M和D | 取決於M和D |
此處的M
指的就是有效位數,D
指的就是小數位數。M
和D
對取值範圍的影響咱們以前在嘮叨浮點數的時候已經介紹過了,可是爲啥M
和D
的取值還會影響到須要的字節數呢?
咱們說定點數是一種精確的小數,爲了達到精確的目的咱們不能把它轉換成二進制以後再存儲(這可能會產生四捨五入的狀況)。咱們能夠以小數點爲界,把一個小數當作是兩個整數被小數點分隔開來的樣子,因此咱們能夠把一個小數分紅3塊來存儲,一是小數點左邊的整數,而是小數點自己,三是小數點右邊的整數,這樣就能夠保證存儲的小數確定是精確的了。
以DECIMAL(6, 1)
爲例,這種類型的取值範圍是-99999.9~99999.9
。因此整數部分絕對值最大的就是99999
,小數部分最大的就是9
,而整數部分的最大值99999
這個十進制數最少須要用3個字節才能存放,小數部分的最大值9
只須要1個字節就能夠存放,因此最後這個定點數類型就須要使用5個字節,各個部分的劃分以下:
因此不一樣的有效位數和小數位數,最終須要的字節數也是不一樣的。能夠看到,與浮點數相比,定點數須要更多的空間來存儲數據,因此若是不是像工資同樣特重要的數據,通常的小數用浮點數就足夠了。
M
和D
都是可選的,默認的M
的值是10,默認的D
的值是0,也就是說下列等式是成立的:
DECIMAL = DECIMAL(10) = DECIMAL(10, 0)
DECIMAL(n) = DECIMAL(n, 0)
複製代碼
另外,有效位數和小數位數也不是無限大的(太大了內存受不了),限制M
的範圍是1~65
,D
的範圍是0~30
,且D
的值不能超過M
。
對於數值類型,包括整數、浮點數和定點數,有些狀況下咱們只須要用到非負數,並且對於整數來講,單純的表示非負數能將正整數的表示範圍提高一倍,因此MySQL
給咱們提供了一個表示非負數值類型的方式,就是在原數值類型後加一個單詞UNSIGNED
:
數值類型 UNSIGNED
複製代碼
你們能夠把它當成一種新類型對待,好比INT UNSIGNED
就表示非負整數,取值範圍是0 ~ 2³²-1
。
字符
分爲兩種,一種叫可見字符
,一種叫不可見字符
。顧名思義,可見字符
就是打印出來後能看見的字符。好比a
,b
,我
,。
... 這樣的人眼能看見的單個國家文字、標點符號、圖形符號、數字等這樣的東東,咱們就叫作一個可見字符
。不可見字符
也好理解,就是打印機或者在黑框框裏打印字符的時候有時候須要換行,打個製表符啥的,或者在輸出某個字符的時候就發出嘟
地一聲,這種咱們看不到,只是爲了控制輸出效果的字符叫作不可見字符
。字符串
就是把字符連起來的樣子,好比abc
,就是由a
、b
、c
三個字符連起來的一個字符串
,下邊列舉了4個字符串的例子:
'我喜歡你'
'me, too'
'give me a hug'
'麼麼噠'
複製代碼
在具體分析MySQL
中各個字符串類型以前,咱們必定要先搞明白字符和字節的區別。字符是面向人的概念,字節是面向計算機的概念。若是你想在計算機中表示字符,那就須要經過字符編碼
來將一個字符映射到一個二進制數據。不幸的是,這種映射關係並非惟一的,不一樣的人制做了不一樣的字符編碼,根據表示一個字符使用的字節數是否是相同的,編碼方式能夠分爲下邊兩種:
固定長度的編碼
採用相同的字節數來表示一個字符,比方說ASCII
編碼方式採用1個字節來表示一個字符,ucs2
採用2個字節來表示一個字符。
變長編碼 採用長度不同的字節來表示不一樣的字符,比方說utf8
編碼方式採用1~3
個字節來編碼一個字符,gb2312
採用1~2
個字節來編碼一個字符。
對於不一樣的字符編碼方式來講,對一樣一個字符可能會產生不同的編碼,好比一樣一個字符:我
,在utf8
和gb2312
這兩種編碼方式下被映射成以下的二進制數據以下:
`utf8`編碼:111001101000100010010001 (3個字節,十六進制表示是:0xE68891)
`gb2312`編碼:1100111011010010 (2個字節,十六進制表示是:0xCED2)
注:十六進制前邊的`0x`是前綴,表示後邊的是16進制數據。
複製代碼
若是你對上邊說的話只知其一;不知其二,那你須要系統的學習一下字符集的相關概念:字符集和編碼介紹。
小貼士: MySQL對`utf8`編碼作了限制,它只能使用3個字節去編碼字符,若是有的字符須要4個字節的話,可使用`utfmb4`,這只是出於性能考慮的,畢竟咱們的大部分場景中不會使用到4個字節編碼的字符。
如今咱們能夠看一下MySQL
中提供的各類字符串類型(注:其中M
表明你要存儲的字符串中最多包含的字符數量,L
表明在實際字符串在某個字符編碼下所佔用的字節數,W
表明某個固定長度編碼方式中編碼一個字符須要的字節數):
類型 | 最大長度 | 存儲空間要求 | 含義 |
---|---|---|---|
CHAR(M) |
M個字符 | L個字節或M個字節或M×W個字節 | 固定長度的字符串 |
VARCHAR(M) |
M個字符 | L+1 或 L+2 個字節 | 可變長度的字符串 |
TINYTEXT |
2⁸-1 個字節 | L+1個字節 | 很是小型的字符串 |
TEXT |
2¹⁶-1 個字節 | L+2 個字節 | 小型的字符串 |
MEDIUMTEXT |
2²⁴-1 個字節 | L+3個字節 | 中等大小的字符串 |
LONGTEXT |
2³²-1 個字節 | L+4個字節 | 大型的字符串 |
CHAR(M)
中的M
取值範圍是0~255
。若是省略掉M
的值,那它的默認值就是1,也就是說CHAR
和CHAR(1)
是一個意思。再回頭看一眼咱們的學生基本信息表,若是你以爲學生的姓名不會超過5個字符,你就能夠指定這個姓名列的類型爲CHAR(5)
。
CHAR(M)
在不一樣的編碼方式下須要的存儲空間也是不同的。假設咱們實際存儲的字符串在某個編碼方式下佔用的字節數爲L
,則CHAR(M)
實際佔用的字節數取決於該編碼方式是不是固定長度的以及M
和L
的值,具體計算方式以下:
若是該編碼方式是固定長度的,W
表明固定長度的字節數,比方說ASCII
編碼方式的W
的值就是1
,ucs2
編碼方式的W
的值就是2
,則CHAR(M)
佔用的存儲空間大小與實際存儲的數據無關,都是M×W
個字節。
若是該編碼方式是變長的,則分爲兩種狀況:
若是L
小於M
,則佔用的存儲空間大小爲M
個字節。
若是L
大於M
,則佔用的存儲空間大小爲L
個字節。
比方說咱們如今使用的字符串類型爲CHAR(5)
,因此如今M
的值就是5
,而後咱們看一下CHAR(5)
實際佔用的存儲空間的狀況:
若是咱們使用固定長度編碼ucs2
進行編碼,無論存儲的數據是啥,最後佔用的存儲空間都同樣。
W
的值是2,因此CHAR(5)
佔用的空間就是5×2=10
個字節。
若是咱們使用變長的utf8
進行編碼。
假設實際存儲的字符串爲我
,由於它用utf8
編碼後的結果是0xE68891
,也就是說實際佔用空間L
的值爲3
,又由於L < M
,因此實際佔用的存儲空間大小爲5
個字節。
假設實際存儲的字符串爲我我
,由於它用utf8
編碼後的結果是0xE68891E68891
,也就是說實際佔用空間L
的值爲6
,又由於L > M
,因此實際佔用的存儲空間大小爲6
個字節。
小貼士: 能夠看到,`CHAR(M)`只有在採用固定長度的字符編碼時所佔用的存儲空間大小纔是肯定的,不然佔用存儲空間大小與實際字符串佔用的字節長度有關。
須要注意的是:若是CHAR(M)
佔用的存儲空間大於實際字符串須要的存儲空間,那多出的存儲空間將被空格
填滿。這種CHAR(M)
的字符串類型有一個很是很差的地方:一旦你肯定了M
的值,若是M
的值很大,而你實際存儲的字符串佔用字節數又不多,會形成存儲空間的浪費。
若是你表中的某個列須要存儲字符串類型的數據,並且這些字符串長短不一,那麼使用CHAR(M)
可能形成很大程度上的浪費,VARCHAR(M)
正是爲了解決這個問題而生的。
VARCHAR(M)
中的M
也是指你要存儲的字符串中最多包含的字符數量,取值範圍是1~65535
。可是MySQL
中還有一個規定,就是某一行包含的全部列中存儲的數據大小不得超過65535個字節,因此VARCHAR(M)
實際可以容納的字符數量確定小於65535。
一個VARCHAR(M)
類型表示的數據由這麼兩部分組成:
真正的字符串內容。
佔用字節數。
假設真正的字符串內容編碼後佔用字節數爲L
,若是L
不大於255,也就是字節數能夠用1個字節來表示,那麼實際佔用的存儲空間就是L+1
個字節;若是L
大於255且不大於65535,也就是字節數能夠用2個字節來表示,那麼實際佔用的存儲空間就是L+2
個字節;又由於某一行包含的全部列中存儲的數據大小不得超過65535個字節,因此L
不可能大於65535。因此實際佔用的存儲空間只多是L+1
個字節或者L+2
個字節。
咱們還用學生的姓名屬性作例子,在使用utf8
編碼方式的狀況下,杜子騰
和範統
這兩個字符串能夠被編碼成以下的樣子(二進制太長了,用16進製表示):
`杜子騰`:0xE69D9CE5AD90E885BE (共9個字節)
`範統`:0xE88C83E7BB9F (共6個字節)
複製代碼
假設咱們給姓名列定義的類型爲VARCHAR(5)
,咱們看一下這兩個字符串的實際存儲示意圖:
從這個圖例也能夠看出了,VARCHAR(M)
佔用的存儲空間大小隨着實際存儲的內容變化而變化,因此咱們說 VARCHAR(M) 是一種可變長度的字符串類型。
雖然VARCHAR(M)
已經能夠存儲很長的字符串了,但是仍是不夠咋辦?對於很長的字符串,設計MySQL
的大叔們給咱們提供了TINYTEXT
、TEXT
、MEDIUMTEXT
、LONGTEXT
四種能夠存儲大型的字符串的類型。它們也都是變長類型,由實際內容和內容長度構成,由於TINYTEXT
最多能夠存儲2⁸-1
個字節,因此內容長度用1個字節就能夠表示,TEXT
最多能夠存儲2¹⁶-1
個字節,因此內容長度用2個字節就能夠表示,剩下的兩個的內容長度佔用的字節數也都是按這個規則算出來的。
不是以前有個規定說某一行包含的全部列中存儲的數據大小不得超過65535個字節麼?那TEXT
、MEDIUMTEXT
、LONGTEXT
這3個類型豈不是不符合規定嘍?哈,因爲MySQL
的大叔會特別關照這幾種類型,因此這幾個類型並不在這個規定的限制範圍以內。你們若是有什麼特別長的文本就能夠考慮使用這幾個類型了。
視角回到咱們的學生信息表,性別一列也須要填寫字符串,可是比較特殊的一點是,這一列只能填男
或者女
,填別的字符串就尷尬了!針對這種狀況,咱們提出了一個叫ENUM
的類型,也稱爲枚舉類型
,它的格式以下:
ENUM('str1', 'str2', 'str3' ⋯)
複製代碼
它表示在給定的字符串列表裏選擇一個。好比咱們的性別一列能夠定義成ENUM('男', '女')
類型。這個的意思就是性別一列只能在'男'
或者'女'
這兩個字符串之間選擇一個,至關於一個單選框~
有的時候某一列的值能夠在給定的字符串列表中挑選多個,假設學生的基本信息加了一列興趣
屬性,這個屬性的值能夠從給定的興趣列表中挑選多個,那咱們可使用SET
類型,它的格式以下:
SET('str1', 'str2', 'str3' ⋯)
複製代碼
它表示能夠在給定的字符串列表裏選擇多個。咱們的興趣一列就能夠定義成SET('打球', '畫畫', '扯犢子', '玩遊戲')
類型。這個的意思就是興趣一列能夠在給定的這幾個字符串中選擇一個或多個,至關於一個多選框~效果就像這樣:
學號 | 姓名 | ··· | 興趣 |
---|---|---|---|
20180101 | 杜子騰 | ··· | '打球', '畫畫' |
20180102 | 杜琦燕 | ··· | '扯犢子' |
20180103 | 範統 | ··· | '扯犢子', '玩遊戲' |
20180104 | 史珍香 | ··· | '畫畫', '扯犢子', '玩遊戲' |
ENUM 和 SET 都是一種特殊的字符串類型,在從字符串列表中單選或多選元素的時候用獲得它們。
咱們有不少場景須要表示時間或日期,好比學生基本信息中的入學時間
就須要用日期的格式保存。MySQL
爲咱們提供了多種關於時間和日期的類型,各類類型能表示的範圍以下:
類型 | 存儲空間要求 | 取值範圍 | 含義 |
---|---|---|---|
YEAR |
1字節 | 1901~2155 | 年份值 |
DATE |
3字節 | '1000-01-01' ~ '9999-12-31' | 日期值 |
TIME |
3字節 | '-838:59:59' ~ '838:59:59' | 時間值 |
DATETIME |
8字節 | '1000-01-01 00:00:00' ~ '9999-12-31 23:59:59' | 日期加時間值 |
TIMESTAMP |
4字節 | '1970-01-01 00:00:01' ~ '2038-01-19 03:14:07' | 時間戳 |
在MySQL5.6.4
這個版本以後,TIME
、DATETIME
、TIMESTAMP
這幾種類型添加了對毫秒、微妙的支持。因爲毫秒、微秒都不到1秒,因此也被稱爲小數秒
,MySQL
最多支持6位小數秒的精度,各個位表明的意思以下:
咱們能夠選擇TIME
、DATETIME
、TIMESTAMP
這幾種類型最多支持到小數點後幾位的時間精度,通用格式爲:
類型(小數秒位數)
其中的`小數秒位數`能夠在0、一、二、三、四、五、6中選擇
複製代碼
好比DATETIME(0)
表示精確到秒,DATETIME(3)
表示精確到毫秒,DATETIME(5)
表示精確到10微秒。若是你在選擇TIME
、DATETIME
、TIMESTAMP
這幾種類型的時候添加了對小數秒的支持,那麼存儲空間須要相應的擴大,不一樣的小數秒精度須要的存儲空間不一樣,以下表:
小數秒精度 | 存儲空間要求 |
---|---|
0 | 0字節 |
1或2 | 1字節 |
3或4 | 2字節 |
5或6 | 3字節 |
也就是說若是你選擇使用DATETIME(1)
,那麼須要的存儲空間就是在DATETIME
的空間上再加上小數秒須要的空間,就是8+1=9
個字節,相似的,DATETIME(3)
就須要10個字節。因此,MySQL5.6.4
這個版本以後的各個類型須要的存儲空間和取值範圍就以下:
類型 | 存儲空間要求 | 取值範圍 | 含義 |
---|---|---|---|
YEAR |
1字節 | 1901~2155 | 年份值 |
DATE |
3字節 | '1000-01-01' ~ '9999-12-31' | 日期值 |
TIME |
3字節+小數秒的存儲空間 | '-838:59:59[.000000]' ~ '838:59:59[.000000]' | 時間值 |
DATETIME |
8字節+小數秒的存儲空間 | '1000-01-01 00:00:00[.000000]' ~ '9999-12-31 23:59:59'[.999999] | 日期加時間值 |
TIMESTAMP |
4字節+小數秒的存儲空間 | '1970-01-01 00:00:01[.000000]' ~ '2038-01-19 03:14:07'[.999999] | 時間戳 |
固然,若是你使用的MySQL
版本還沒到5.6.4
,那就不支持小數秒,能夠翻上去看原來的存儲空間和取值範圍。下邊咱們來詳細看一下各類類型。
單純的表示一個年份值而已~不過它只有1個字節大小,因此存儲的年份值範圍有限,若是咱們想存儲更多的年份值,能夠考慮更換成SMALLINT
(2字節)或者字符串類型啥的~
顧名思義,DATE
表示日期,格式是CCYY-MM-DD
;TIME
表示時間,格式是hh:mm:ss[.uuuuuu]
,DATETIME
表示日期+時間,格式是CCYY-MM-DD hh:mm:ss[.uuuuuu]
。其中的CC
、YY
、MM
、DD
、hh
、mm
、ss
、uuuuuu
分別表示世紀、年、月、日、時、分、秒、小數秒。
須要注意的是,DATETIME 中的時間部分表示的是一天內的時間,而 TIME 表示的是一段時間,並且能夠表示負值。
1970-01-01 00:00:00
註定是一個特殊的時刻,這一天被稱爲位零日
,也稱爲紀元
,MySQL
中把某個時刻距離1970-01-01 00:00:00
的秒數稱爲時間戳
。比方說當前時間是2018-01-24 11:39:21
,距離1970-01-01 00:00:00
的秒數爲1516765161
,那麼2018-01-24 11:39:21
這個時刻的時間戳就是1516765161
。不過在MySQL5.6.4
以後,時間戳的值也能夠加入小數秒。
用時間戳存儲時間的好處就是,它展現的值能夠隨着時區的變化而變化。比方說咱們把2018-01-24 11:39:21
這個時刻存儲到一個TIMESTAMP
的列中,那麼在中國你看到的時間就是2018-01-24 11:39:21
,若是你去了日本,他們哪裏的使用的是東京時間,比北京時間早一個小時,因此他們那顯示的就是2018-01-24 10:39:21
。而若是你用DATETIME
存儲2018-01-24 11:39:21
的話,那不一樣時區看到的時間值都是同樣的。
MySQL中有設置時區的方式,咱們這裏先不嘮叨,等用到的時候再說啊
複製代碼
若是你是專業的程序員的話,確定對二進制數據不陌生,有時咱們也有存儲這些二進制數據的需求。MySQL
提供了下邊這些數據類型供咱們使用:
類型 | 最大長度 | 存儲空間要求 | 含義 |
---|---|---|---|
BIT(M) |
M個位 | (M+7)/8個字節 | 固定長度的字符串 |
BINARY(M) |
M個字節 | M個字節 | 固定長度的字符串 |
VARBINARY(M) |
M個字節 | L+1 或 L+2 個字節 | 可變長度的字符串 |
TINYBLOB |
2⁸-1 個字節 | L+1個字節 | 很是小型的字符串 |
BLOB |
2¹⁶-1 個字節 | L+2個字節 | 小型的字符串 |
MEDIUMBLOB |
2²⁴-1 個字節 | L+3個字節 | 中等大小的字符串 |
LONGBLOB |
2³²-1 個字節 | L+4個字節 | 大型的字符串 |
對於BIT(M)
來講,M
指的是該類型最多能存儲的二進制位的個數,好比BIT(3)
就是指最多能存放3個二進制位。而內存空間最少的分配單位就是字節,因此不足一字節的按一字節計算,因此存儲空間就是(M+7)/8個字節。
BINARY(M)
和VARBINARY(M)
對應於咱們前邊提到的CHAR(M)
和VARCHAR(M)
,都是前者是固定長度的類型,後者是可變長度的類型,只不過BINARY(M)
和VARBINARY(M)
是用來存放字節的,而CHAR(M)
和VARCHAR(M)
是用來存儲字符的。
TINYBLOB
、BLOB
、MEDIUMBLOB
、LONGBLOB
是針對數據量很大的二進制數據提出的,好比圖片、音頻、壓縮文件啥的。它們很像TINYTEXT
、TEXT
、MEDIUMTEXT
、LONGTEXT
,不過BLOB
是用來存儲字節的,而TEXT
是用來存儲字符的而已。在一般狀況下,咱們通常都是隻存儲個文件路徑而已,而後使用操做系統的文件系統去訪問文件的~
數據庫底層使用表來存放數據的,一張表有不少列,每一個列都有可能存放不一樣格式的數據,不一樣格式的數據是不能混用的,因此MySQL
提出了許多類型來存儲不一樣格式的數據。
用來存儲整數的類型有TINYINT
、SMALLINT
、MEDIUMINT
、INT
、BIGINT
這幾種,它們須要的存儲空間不一樣,因此能表示的整數範圍也不一樣。
用來存儲小數的有FLOAT
、DOUBLE
、DECIMAL
類型,前兩個屬於浮點型,後一個屬於定點型,浮點型更省存儲空間,而定點型更精確,這些表示小數的類型均可以使用(M, D)來指定小數的有效位數和小數位數。
用來存儲字符串的有CHAR(M)
、VARCHAR
、TEXT
、MEDIUMTEXT
、LONGTEXT
這幾種,它們實際佔用的字節存儲空間依賴與咱們當前使用的字符編碼,由於在不一樣編碼下,同一個字符可能被編碼成不一樣長度的字節數據,其中的CHAR(M)
是固定長度的類型,其他集中都是可變長度的類型,真實長度取決於實際的字符串長度。
用來存儲時間的有YEAR
、DATE
、TIME
、DATETIME
、TIMESTAMP
這幾種類型,須要注意的是,在在MySQL5.6.4
這個版本以後,TIME
、DATETIME
、TIMESTAMP
這幾種類型添加了對小數秒的支持,可是存儲小數秒又要使用額外的存儲空間。另外,TIMESTAMP
這種類型存儲的是自1970-01-01 00:00:00
時刻起的秒數,因此在不一樣時區下會顯示不一樣的時間值。
用來存儲二進制數據的有BIT(M)
、BINARY(M)
、VARBINARY(M)
、TINYBLOB
、BLOB
、MEDIUMBLOB
、LONGBLOB
這幾種,除了BIT(M)
是以二進制位爲單位的之外,其他的類型都是以字節爲單位的,而且它們的使用相似字符串中的各類類型,只不過一個是以字符爲單位,一個以字節爲單位而已~
本系列專欄都是MySQL入門知識,想看進階知識能夠到小冊中查看:MySQL是怎樣運行的連接 。小冊的內容主要是從小白的角度出發,用比較通俗的語言講解關於MySQL內核的一些核心概念,好比記錄、索引、頁面、表空間、查詢優化、事務和鎖等,總共的字數大約是三四十萬字,配有上百幅原創插圖。主要是想下降普通程序員學習MySQL內核的難度,讓學習曲線更平滑一點~