MySQL學習筆記之數據類型
數據類型在所有的數據庫使用當中,都是避免不了的部分。以前每次寫SQL語句,對於定義成哪種數據類型總是迷迷糊糊,今天就來徹底弄清。以下介紹僅針對MySQL 5.5以上版本。
一、字符串類型
1、char和varchar
以前在建表語句中,定義到字符串類型只會用varchar,但是它後面要指定一個數字,這個數字具體代表什麼一知半解。char和varchar兩個類型後面都要跟上一個數字,例如char(10),varchar(20)。
看過官方文檔後發現,這裡的數字表示的是最大字符個數,注意是字符數,而不是字節數!在嚴格的SQL模式下,插入的字符串數據如果字符數超過這個值,分兩種情況:
①如果尾部超出部分全都是空格,則截去超出部分後插入,產生一個警告;
②如果尾部超出部分含非空格字符,插入失敗,直接報錯。
在非嚴格SQL模式下,兩種情況都會直接截去超出部分後插入。
括號裡面的數字究竟能設為多大呢?官方說明是,char的可以設為0~255,varchar的可以設為0~65535。對於char沒有任何問題,但對於varchar,經過實際操作發現沒那麼簡單。
MySQL不管對於什麼樣的存儲引擎,有一個統一的設定,那就是一行數據的總字節數,不能超過65535。而字符有英文字符,有中文字符,還有其他語言的字符,而且各種編碼下,有的字符一個占1字節,有的字符一個占2個或3個字節。而MySQL的默認編碼類型是utf-8,一個中文字符占到3個字節,如果某個字段指定為varchar(65535),那麼單這一個字段,最大字節數就可能達到65535*3,遠遠超出了一行數據的最大設定65535字節。比如執行如下語句:
create table t_planet
(
name varchar(65535)
);
會提示如下錯誤: create table t_planet ( name varchar(65535) ) Error Code: 1074. Column length too big for column 'name' (max = 21845); use BLOB or TEXT instead
注意這裡的錯誤提示,它提示name字段的最大字符數只能為21845,也就是65535除以3。因為在默認的utf-8編碼下,最壞情況下會出現全為中文字符的情況,根據一個中文字符占3字節,所以最大字符數就是65535/3。
如果把字符集改為所有字符只占1字節的latin1,字符數最大值就可以達到65535了。
create table t_planet
(
name varchar(65535)
) character set latin1;//整張表格的字符集指定為latin1
以上只是對最大字符數做的設定。具體到一個字符串究竟占用了多少字節,char和varchar的計算方法不一樣。首先當然要根據實際的字符集,算出各個字符各自占用的字節數,然後求和。這裡為了方便起見,假定每個字符都占一個字節。這樣,對於char(M),實際占用的字節數就永遠都是M,因為如果字符數不滿M,後面用空格補充,空格也占用字節數。當然這是存儲時的情況,select顯示時是把尾部空格全部去掉的。
而對於varchar(M),實際占用的字節數絕大多數小於M,輸入幾個字符就是幾個字符,不會自動填充。當然,因為字符數不確定,就要額外增加1到2個字節記錄字符個數,<=255個字符用1字節記錄,>255&&<=65535個字符就用2字節記錄。這樣,一個varchar(M)的字符串,實際占用空間大小就是“實際字符數+1或+2”。
由上面分析可以得知,varchar表面上完全可以取代char,實際未必,因為varchar有額外的空間占用。更重要的是,在以字符串創建索引、進行排序等操作時,由於char的字符數固定,擁有更高的效率。比方說有一個學號字段,有9位數也有10位數,表面上應該用可變字符串varchar,實際上用固定字符串char(10)是更好的選擇。
2、enum
enum可以理解為枚舉類型,它給出n個現成的字符串,插入的數據只能從這幾個字符串裡面選擇。
create table country
(
place enum('Japan','China','Russia','Brazil','America')
);
insert into country values ('China');
插入數據的語句跟正常的一樣。一旦插入的字符串不在范圍裡面,如果處於嚴格的SQL模式,會直接報錯,插入失敗;否則會插入空字符串('')。當然也可以插入null。
如果enum限定為not null,默認值就是第一個字符串,否則就是null。
使用enum類型除了可以限定插入的具體值以外,還有很重要的一點就是節省空間。如上例插入'China'的時候,實際上並沒有插入5個字節的字符,而是僅插入一個字節的數組索引,這個索引是2,指向第二個字符串,而不是額外為字符開辟存儲空間。記錄達到成千上萬的時候,能節省多少空間可想而知。
另外,建議枚舉值不要用'1','2','3'這樣的數值型表示,MySQL對這種形式處理起來往往會出現意想不到的結果。
二、整數類型
MySQL中的整數類型使用起來很簡單,樣式就是:INT [UNSIGNED] [ZEROFILL]。其中第一個參數是類型名,可以是其他的int型;第二個參數指明是否帶符號整數,默認含負數范圍,指定為unsigned後只能為正數或0,可以使正數范圍擴大一倍;第三個參數指明數字前是否以0填充,以使該字段所有數據位數一致。
MySQL中整數類型眾多,其中INT和SMALLINT是SQL語言的標准類型,其他是MySQL的補充類型。
三、小數類型
浮點數:float和double,跟編程語言裡面的單雙精度一樣。
float占4字節,表示范圍:負數部分-3.402823466E+38 到 -1.75494351E-38,正數部分與之對稱 1.75494351E-38 到 3.402823466E+38
double占8字節,因為平時極少涉及很高的精度,此處略。
float和double都可以定制符合自己要求的位數,格式float(M,D),其中M表示整數和小數部分所有數字的個數最大值,D表示小數點後的小數位數。實際應用中,一旦設定,小數部分必須達到D位,不足補0,超出四捨五入;整數部分最多只能為M-D位。
注意在用==或!=比較時會產生誤差,比較結果往往不確定。