1、MySQL 數據類型
MySQL 支持多種類型,大致可以分為三類:數值、日期/時間和字符串(字符)類型。
1.2、mysql中編碼和字符
在 mysql 中,一個中文漢字所占的字節數與編碼格式有關:
- 如果是GBK編碼,則一個中文漢字占2個字節,英文占1個字節
- 如果是UTF8編碼,則一個中文漢字占3個字節,而英文字母占1字節。
比如定義某個字段數據類型為:varchar(32),表示這個可以存儲 32 個字符,此時表示的是字符,所以跟中英文無關,也就是該字段可以存儲 32 個中文,或者是 32 個英文,或者是 32 個中文和英文的混搭都行。但如果字符數超過 32 個的話就會報錯。
2、數值類型
MySQL 支持所有標准 SQL 數值數據類型,mysql 的數值數據類型可以大致划分為兩個類別,一個是整數,另一個是浮點數或小數。並且 MySQL 允許我們指定數值字段中的值是否有正負之分(UNSIGNED)或者用零填補(ZEROFILL)
在 MySQL 中支持的 5 個主要整數類型是 TINYINT,SMALLINT,MEDIUMINT,INT 和 BIGINT。這些類型在很大程度上是相同的,只有它們存儲的值的大小是不相同的。浮點型有:FLOAT、DOUBLE、DECIMAL。
下面的表顯示了需要的每個數值類型的存儲所占用的字節和可表示的數值范圍:
1 bit 即 1位 1字節 = 8 bit 1K = 1024字節 1M = 1024K
類型 | 大小 | 范圍(有符號,默認) | 范圍(無符號) | 用途 | 對應java類 |
---|---|---|---|---|---|
TINYINT | 1 Bytes | (-128,127) | (0,255) | 小整數值 一個很小很小的整數 |
Integer |
SMALLINT | 2 Bytes | (-32 768,32 767) | (0,65 535) | 大整數值 一個小整數 |
Integer |
MEDIUMINT | 3 Bytes | (-8 388 608,8 388 607) | (0,16 777 215) | 大整數值 一個中等大小的整數 |
Integer |
INT或INTEGER | 4 Bytes | (-2 147 483 648,2 147 483 647) | (0,4 294 967 295) | 大整數值 一個int大小的整數 (大都用來做id) |
Integer |
BIGINT | 8 Bytes | (-9,223,372,036,854,775,808,9 223 372 036 854 775 807) | (0,18 446 744 073 709 551 615) | 極大整數值 一個蠻大的整數(也常用來做id) |
Long |
FLOAT | 4 Bytes | (-3.402 823 466 E+38,-1.175 494 351 E-38),0,(1.175 494 351 E-38,3.402 823 466 351 E+38) | 0,(1.175 494 351 E-38,3.402 823 466 E+38) | 單精度,浮點數值。 學生成績、允許有誤差的、單精度浮點數 |
Float |
DOUBLE | 8 Bytes | (-1.797 693 134 862 315 7 E+308,-2.225 073 858 507 201 4 E-308),0,(2.225 073 858 507 201 4 E-308,1.797 693 134 862 315 7 E+308) | 0,(2.225 073 858 507 201 4 E-308,1.797 693 134 862 315 7 E+308) | 雙精度,浮點數值。 學生成績、允許有誤差的、雙精度浮點數 |
Double |
DECIMAL | 對DECIMAL(M,D) ,如果M>D,為M+2否則為D+2 | 依賴於M和D的值 例如定義 DECIMAL(5,2) ,則表示最大位數為5位,小數點后2位,於是取值范圍為 -999.99至999.99 |
依賴於M和D的值 | 小數值。 用來計算工資、盈利、金融方面 |
Java.math.BigDecimal |
比如 INT 類型,該類型所占字節為 4 個字節。比如數據庫中某列的字段類型為 INT,則每條數據的該列的數據都會占服務器容量的 4 個字節的存儲容量,並且該列所能顯示的數值范圍只能是 -128~127 ,或者如果該列是無符號的話,則范圍是 0~255。如果你存儲超出最大范圍則會提示 out of range value ....,比如往 INT 且有符號的數據類型里面存儲 2147483648 的值,則會報錯並且不會存儲成功。
2.1、整數類型的長度
常用的整數數據類型有 tinyint ,smallint ,mediumint , int ,bigint 共計5種。
在聲明整數類型列時,我們可以跟上一個數值,例如 int(n) ,但實際上這里的 n 跟存儲沒有什么關系,無論 n 是什么,INT 數據類型都是 4 個字節,只能存儲 -2 147 483 648~2 147 483 647(有符號時)范圍的數據。
在mysql手冊中這個 n 表示最大顯示寬度,顯示寬度與存儲大小和數據類型所能包含的值的范圍無關,最大有效的顯示寬度是255,即 n 的值最大是 255。
比如我聲明一個字段為 `number` INT(5) ,此時該 number 字段也是占 4 個字節,也只能存儲 -2 147 483 648~2 147 483 647(有符號時)范圍的數據。這個 n 的作用只有在我們給列加上 ZEROFILL(用 0 填充)屬性時才會體現出來,並且只有在使用一些特定的客戶端輸出時才會有體現。比如:
`number` int(5) unsigned zerofill -- 加上zerofill屬性則必須同時加unsigned屬性
此時,當該列某條數據的數字小於 5 位時,在某些特定的客戶端檢索輸出時,會在數字前 “補0”,湊足5位數字。例如存儲的數字是123,那么輸出00123 。如果大於 5 位則原樣顯示原數字。
注意,不是在數據庫中存儲時會自動補 0 ,而是在某一些客戶端查詢輸出時才有顯示效果,目前僅發現使用在MySQL Shell才有顯示效果,其他客戶端連接時均無。
所以說,基本沒有開發者會使用這個特性,因為基本沒什么用。
2.2、浮點型
FLOAT 類型固定占用4個字節, DOUBLE 類型固定占用8個字節,邏輯和上述的整型類似。
DECIMAL 類型的定義方式是 DECIMAL(M,D) ,其中 M 表示最大位數,D 表示小數點右側的位數。這里的“位”不是二進制的比特位,而是指十進制的數字的位數。
例如我們定義 DECIMAL(5,2) ,則表示最大位數為5位,小數點后2位,於是取值范圍為 -999.99至999.99 。可以這樣理解:M-D 的值為小數點前的位數,D 的值為小數點后的位數,要算取值范圍則各個位置填充9,取正負范圍。那么容易計算 DECIMAL(5,1) 的取值范圍是 -9999.9至9999.9 ;DECIMAL(4,2) 的取值范圍是 -99.99至99.99 。
DECIMAL(M,D) 的存儲方式和其他數字類型都完全不同,它是以字符串形式進行存儲的。這可能有點不好理解,以整型 tinyint 為例,它存儲的值是直接為十進制到二進制的轉換,以無符號型為例,當需要存入的值為100值,將100轉化為二進制為1100100 ,使用1個字節即8位記錄,實際存入的是 01100100 。但是用 DECIMAL 類型存儲時,比如定義 DECIMAL(3,0) ,存入100時,實際存入的是由字符“1”,“0”,“0”拼接而成的字符串“100”的二進制值,存入時占用3個字節,分別是31,30,30(注意這是十六進制)。
1個數字字符占用1個字節,因此定義為 DECIMAL(M,D) 占用 M 個字節。(同上所述,M個字節為數據本身的占用空間,另外描述該數據的元數據還固定占用2個字節的空間)。
需要注意的是, DECIMAL 類型在存儲時有補0操作。小數點前不足,向更高位補0,小數點后不足,向更低位補0。
以 DECIMAL(5,2) 為例,如果准備存入9.5,小數點前應為3位,缺2位,小數點后應為2位,缺1位,各補0后,實際存入 '009.50' ,轉化為十六進制為30 30 39 2E 35 30 。但是在檢索輸出時,小數點前的0一般會省略,而小數點后的0會保留,這一點也需要注意。
可參考:https://zhuanlan.zhihu.com/p/111028232
3、字符串類型
MySQL 提供了 8 個基本的字符串類型,包括 CHAR、VARCHAR、BINARY、VARBINARY、BLOB、TEXT、ENUM 和 SET,可以存儲的范圍從簡單的一個字符到巨大的文本塊或二進制字符串數據。
類型 | 大小 | 用途 | 對應java類 |
---|---|---|---|
CHAR | 0-255 bytes(字節) | 定長字符串 | String |
VARCHAR | 0-65535 bytes | 變長字符串 | String |
TINYTEXT | 0-255 bytes | 短文本字符串 | String |
TEXT | 0-65 535 bytes | 長文本數據 | String |
MEDIUMTEXT | 0-16 777 215 bytes | 中等長度文本數據 | String |
LONGTEXT | 0-4 294 967 295 bytes | 極大文本數據 | String |
3.1、字符串類型長度
常用的字符串類型的數據類型有 CHAR 和 VARCHAR 兩種,兩者后面都必須要跟上一個數字表示長度,例如 CHAR(10)、VARCHAR(10)。
char(n) 和 varchar(n) 括號中的 n 代表最大可容納的字符的個數,並不代表字節個數。注意,一個中文和一個英文都是 1 個字符,只不過 mysql 的編碼格式不同時,1 個中文和 1 個英文所占用的存儲字節不同而已。(雖然在早期的版本中,n 指的是字節數,但已經是非常舊的版本了,估計一般人也用不到)
CHAR(n) 和 VARCHAR(n) 都是表示可存儲 n 個字符,但是 char 類型在少於 n 個字符時,會在字符串的右邊使用空格來填充以達到 n 個字符。
比如:CHAR(4) 和 VARCHAR(4) ,對於 CHAR(4) 表示固定容納4個字符,當少於4個字符時,會使用空格填充空缺的部分,如果超過4個字符,會自動截斷超出部分。例如你存入數據為 'ab' ,實際會存入 'ab ' (ab后有2個空格)。但是如果我們使用 select 語句來查詢 char 類型的字段時,會發現根本就沒有自動補空格,這是因為 CHAR 字段在檢索輸出時,會自動省略右側的空格。
VARCHAR 是 CHAR 類型的一個變體,它是一種可變長度的字符串類型,並且在聲明時也必須要指定字符長度。VARCHAR 類型對於未達到 n 字符的情況不會補空。
CHAR 和 VARCHGAR 不同之處在於 MYSQL 數據庫處理這個指示器(即 n)的方式:CHAR 把這個大小視為值的大小,在長度不足的情況下就用空格補足。而 VARCHAR 類型只會把 n 作為限制字符串的最大長度,短於指示器長度的 VARCHAR 類型不會被空格填補,但長於指示器的值仍然會被截短。
關於計算 VARCHAR 類型字符串的占用空間,有一點需要說明的是, VARCHAR 類型字符串的占用空間實際上包含2部分,一是存儲數據本身占用的空間,二是描述數據的元數據占用的空間,例如 VARCHAR 類型會使用1個字節記錄存入數據實際的字符數。
比如下面示例說明 varchar 字段的字符長度和占用存儲字節數:
(1) 'a啊b' —— 字符數為3,不補空,實際存入為 'a啊b' ,字符數為3,字節數為 1+3+1=5 。
(2)'a啊b哈ccccccccc' —— 字符數超出4,僅保留前4個字符,因此實際存入 'a啊b哈' ,字符數:4,字節數:1+3+1+3=8 。這種情況和 CHAR 類型處理一致。
(3)'a啊和哈' —— 字符數剛好為4,不需要截斷和補齊,因此實際存入 'a啊和哈' ,字符數:4,字節數:1+3+3+3=10
兩者的使用場景:因為 VARCHAR 類型可以根據實際內容動態改變存儲值的長度,所以在不能確定字段需要多少字符時使用 VARCHAR 類型可以大大地節約磁盤空間、提高存儲效率。但如果確切知道字符串長度,比如就在50~55之間,那就用 CHAR,因為 CHAR 類型由於本身定長的特性使其性能要高於 VARCHAR。
4、日期和時間類型
在處理日期和時間類型的值時,MySQL 帶有 5 個不同的數據類型可供選擇。它們可以被分成簡單的日期(DATE)、時間類型(TIME)、年份(YEAR)、混合日期(DATETIME)、時間類型(TIMESTAMP)。
每一個時間、日期類型都有合法的取值范圍,當指定確定不合法的值時,系統將“零”值插入數據庫中。
類型 | 大小 ( 固定長度、單位為字節) |
范圍 | 格式 | 用途 |
---|---|---|---|---|
DATE | 3 | 1000-01-01/9999-12-31 | YYYY-MM-DD(年月日) | 日期值 |
TIME | 3 | '-838:59:59'/'838:59:59' | HH:MM:SS(時分秒) | 時間值或持續時間 |
YEAR | 1 | 1901/2155 | YYYY | 年份值 |
DATETIME | 8 | 1000-01-01 00:00:00/9999-12-31 23:59:59 | YYYY-MM-DD HH:MM:SS(年月日時分秒) | 混合日期和時間值 |
TIMESTAMP | 4 | 1970-01-01 00:00:00/2038 結束時間是第 2147483647 秒,北京時間 2038-1-19 11:14:07,格林尼治時間 2038年1月19日 凌晨 03:14:07 |
YYYYMMDD HHMMSS | 混合日期和時間值,時間戳 |
這個時間的對應的Java類、只要格式正確、都是可以取的,主要看需求是什么。不管你后端是String、Date 類型、只要格式是對應的就是可以的。
4.1、DATETIME
DATETIME類型后面可以接后綴,當然也可以沒有,如datetime、datetime(3)、datetime(6),這個后綴是用來定義毫秒的精度的。這個后綴最大是6,超過就會報錯。
假設建表語句為:
則存儲結果分別為:
5、二進制數據類型
主要包含下列幾種數據類型:tityblob,blob,mediumblob,longblob。
mysql類型名 | 描述 |
---|---|
tityblob | 不超過 255 個字符的二進制字符串 |
blob | 二進制形式的長文本數據 |
mediumblob | 二進制形式的中等長度文本數據 |
longblob | 二進制形式的極大文本數據 |