重學MySQL系列(三):MySQL數據類型詳解

原創做者,公衆號【程序員讀書】,歡迎關注公衆號,轉載文章請註明出處哦。mysql

在這篇文章中,咱們來學習MySQL的數據類型,數據類型是MySQL學習中比較基礎的知識,但同時也是比較容易被忽略的知識,所以有必要認真學習一下。程序員

固然,不少對數據庫有了解的小夥伴應該都知道,MySQL的數據類型,是在建立數據表(Table)的時候,用於指數據表中字段(Field)的類型,即規定字段用存儲什麼樣的數據。sql

好比下面咱們在建立數據表時,在每一個字段名稱後面指定了數據表的數據類型。數據庫

CREATE TABLE users(
    id INT NOT NULL AUTO_INCREMENT, 
    username VARCHAR(32) NOT NULL,
    email VARCHAR(50) NOT NULL,
    phone CHAR(11) NOT NULL,
);
複製代碼

如何查看數據類型

對於已經建立好的數據表,咱們可使用SHOW CREATE TABLE語句查看具體數據表的原始建表SQL語句,好比咱們想知道上面的users數據表的建表語句,能夠這樣:json

SHOW CREATE TABLE users;
複製代碼

執行了上面的語句後,就會打印上面咱們建立數據表的原始SQL語句。數組

MySQL的數據類型

目前MySQL支持的數據類型有:數字類型字符串類型(包括字符)、時間與日期類型空間類型JSON類型,不一樣數據類型有不一樣的特性,咱們可從該類型的存儲空間、取值範圍、默認值、如何進行比較,是否能夠索引等等方面對其進行學習。bash

注:空間數據類型在平時使用並不太經常使用,所以在咱們的文章中便不做介紹了。函數

數字數據類型

MySQL的數字類型可分爲整數類型定點型類型浮點數類型位類型四種類型,下面表格是這四種數據類型的更細緻劃分,咱們能夠從表格中對全部數字類型有必定的瞭解。學習

數據類型定義 存儲空間佔用量 取值範圍
TINYINT[(M)] 1個字節 帶符號:-128~127(-2^{7}到2^{7}-1)
無符號:0~255(2^{8}-1)
SMALLINT[(M)] 2個字節 帶符號:-32768~32767(-2^{15}到2^{15}-1)
無符號:0~65535(2^{16}-1)
MEDIUMINT[(M)] 3個字節 帶符號:-8388608~8388607(-2^{23}到2^{23}-1)
無符號:0~16777215(2^{24}-1)
INT[(M)] 4個字節 帶符號:-2147683648~2147683647(-2^{31}到2^{31}-1)
無符號:0~4294967295(2^{32}-1)
BIGINT[(M)] 8個字節 帶符號:-128~127
無符號:0~255
DECIMAL([M[,D]]) 可變長度 其取值範圍由M和D的值決定
FLOAT[(M)] 4個字節 最小非零值 :\pm 1.175494351E-38
最大非零值:\pm 1.175494351E-38
DOUBLE[(M)] 8個字節 最小非零值 :\pm 1.175494351E-38
最大非零值:\pm 1.175494351E-38
BIT[(M)] 1~4個字節 0到2^{M}-1

整數類型

整數類型用於存儲整數,根據其存儲的字節大小可分爲TINYINTSMALLINTMEDIUMINT,INT,BIGINT,分別佔用1,2,3,4,8個字節的大小,存儲範圍從 -2^{(N-1)}到2^{(N-1)}-1,其中N是類型的存儲空間的位數(bit,1個字節8bit)。spa

UNSIGNED

通常整數都支持正負值,不過可使用可選的屬性UNSIGNED,使其不容許負值,這樣的話,可使用存儲的正數上限提升一倍,好比TINYINT的範圍由-128~127變爲0~255

CREATE TABLE test_int(
    id int unsigned not null
);
複製代碼

AUTO_INCREMENT

對整數類型,在建立數據表時,能夠指定AUTO_INCRMENT屬性,讓該字段能夠變成一個能夠自動增加的序列,如:

CREATE TABLE test_int(
    id INT UNSIGNED NOT NULL AUTO_INCRMENT PRIMARY KEY,
    name VARCHAR(32) NOT NULL
);
複製代碼

實數類型

實數類型分爲浮點數定點數類型兩種,定點數類型一種是精確值類型,DECIMAL就是定點數類型,浮點數是一種是近似值類型,FLOATDOUBLE就是浮點數類型。

浮點數類型存四捨五入的問題,所以在有須要精確運算的時候,可使用定點數或整數數據,避免計算偏差。

浮點數也可使用UNSIGNED屬性,與整數同樣,這會讓浮點數變成所有是正數,不能支持負數。

浮點數也可使用AUTO_INCRMENT,這會讓浮點數的表現與整數同樣了。

位數類型

MySQL5.0之前,BIT類型是TINYINT的同義詞,在MySQL 5.0之後,BIT類型是一種用於存儲位字段值的類型。

BIT字段的值的格式爲:0bval,b'val'B'val'val表示的是0或1組成的位字段常量值。

下面合法的BIT類型常量值:

0b11111
b'11111'
B'11111'
複製代碼

而下面則不合法的常量值:

0B'11111'
b11111
B11111
複製代碼

使用BIT字段時,能夠指定一個長度M,即BIT(M)M的取值爲1~64,,因此BIT類型的字段佔用1~4個字節的長度。

#示例表1
CREATE TABLE test_bit_1(
    id bit
);
#示例表2
CREATE TABLE test_bit_2(
    id bit(8)
);
複製代碼

上面的示例表1中,咱們沒有指定M,因此默認值爲1,即咱們只能向示例表1插入1個位值。

# 正確
INSERT INTO test_bit_1 VALUES(B1);
# 錯誤
INSERT INTO test_bit_1 VALUES(B11);
#正確
INSERT INTO test_bit VALUES(B11111111);
#正確
INSERT INTO test_bit VALUES(B000011111111);
# 錯誤
INSERT INTO test_bit VALUES(B000111111111);
複製代碼

字符串類型

字符串類型是MySQL中最經常使用的數據類型,也是比較靈活的數據類型,學習字符串數據,也會討論到字符集與轉義字符等知識,由於比較複雜。

MySQL數據庫中,字符串的字段值可使用雙引號("")或單引號('')來括起來,好比:

'test'
"mysql"
複製代碼

若是字符串值裏面自己就包含雙引號或單引號時,若是隻包含單引號,則可使用雙引號來引用字符串,反引亦然,而若是一個字符串裏面同時包含單雙引號時,也可使用反斜槓(\)進行轉義,好比:

"I'm Programmer"
'He is "Programmer"'
'I\'m Programmer' 複製代碼

下面的表格所展現的MySQL支持的全部字符串數據類型:

數據類型定義 存儲空間佔用量 最大長度
BINARY([M]) M個字節 M個字節
VARBINARY([M]) M個字節 L+1或L+2個字節
CHAR([M]) M個字符 M*w個字節
VARCHAR([M]) M個字符 L+1或L+2個字節
TINYBLOB 2^{32}-1個字節 L+1個字節
BLOB 2^{32}-1個字節 L+2個字節
MEDIUMBLOB 2^{32}-1個字節 L+3個字節
LONGBLOB 2^{32}-1個字節 L+4個字節
TINYTEXT 2^{8}-1個字符 L+1個字節
TEXT] 2^{16}-1個字符 L+2個字節
MEDIUMBLOB 2^{24}-1個字符 L+3個字節
LONGTEXT 2^{32}-1個字符 L+4個字節
SET('value1','value2',.....) 1或2個字節 64個成員
ENUM('value1','value2',.....) 1,2,3,4或8個字節 65535個成員

MySQL的字符串數據類型能夠分爲二進制字符串類型非二進制字符串類型兩種,所以上面表格中的數據類型,還能夠這樣劃分同樣:

二進制字符串類型 非二進制字符串類型
BINARY CHAR
VARBINARY VARCHAR
TINYBLOB TINYTEXT
BLOB TEXT
MEDIUMBLOB MEDIUMTEXT
LONGBLOB LONGTEXT

二進制字符串類型用於存儲二進制數據,其存儲的尺寸用字節數來計算,而非二進制字符串用於保存其餘字符串數據,其存儲的尺寸用字符數來計算,其存儲的長度能夠經過在類型跟一個參數M來指定,如:

CREATE TABLE test_string(
    a BINARY(20),
    b CHAR(20)
);
複製代碼

上面的示例數據表中,字段a是用於二進制數據,表示能夠存儲20個字節,而字段b存儲非進制數據類型,表示能夠存儲20個字符。

對於非二進制字符串,在存儲和解析時,還須要指定屬於什麼字符集和排序方式,不一樣的字符集與排序方式二進制字符串類型的存儲空間與比較方式。

關於字符集和排序方式的知識,之後有機會再討論。

CHAR與VARCHAR

CHARVARCHAR在於,CHAR是定長字符串數據類型,而VARCHAR是可變長度的字符串數據類型。

CHAR的長度取值範圍是1~255,默認值1,但CHAR(0)是合法,佔用1個位,表示空字符串。

VARCHAR的取值範圍是1~65535,不過VARCHAR的最大長度通常小於65535,所以MySQL中數據行的最大長度也是65535,況且VARCHAR還須要額外兩個字節來記錄其目前的存儲長度。

BINARY與VARBINARY

BINARYVARBINARY的區別與CHARVARCHAR的區別是相似的。

BLOB家族與TEXT家族

BLOB是包含TINYBLOB,BLOB,MEDIUMBLOB,LONGBLOB系列數據類型的家族,用於存儲二進制字符串,好比圖片、聲音等數據,而TEXT是包含TINYTEXT,TEXT,MEDIUMTEXT,LONGTEXT系列數據類型的家族用於存儲非二進制字符串,因此TEXT系列的類型存儲與解析與字符集有關。

使用MEMORY存儲引擎的數據表不支持BLOBTEXT這兩種數據類型。

ENUM與SET

ENUM是一種特殊的字符串類型,佔用1或2個字節,也就是說ENUM類型能夠設置65535個成員,ENUM類型與通常的字符串類型不一樣,設置爲ENUM類型的字段,只能存儲預先定義好的字符串值。

以下所示,咱們建立一個users表,該表有一個定義爲ENUM類型的gender字段:

CREATE TABLE users(
    id int not null,
    username varchar(32) not null,
    gender enum('f','m')
);
複製代碼

下面的語句能夠正確地寫入數據表:

INSERT INTO users values(1,'test_1','f');
INSERT INTO users values(2,'test_2','m');
複製代碼

而下面寫入了一個gender字段未定義的值

INSERT INTO users values(3,'test_3','d');
複製代碼

因此會報以下所示的錯誤:

ERROR 1265 (01000): Data truncated for column 'gender' at row 1
複製代碼

ENUM同樣,SET也是一種特殊的字符串類型,而且同樣只能存儲預先定義好的字符串值,SET根據預先定義值的數值會佔用1,2,4或8個字節,但只能存儲64個成員。

時間與日期類型

MySQL爲存儲時間與日期提供了YEARDATETIMEDATETIMETIMESTAMP等數據類型,分別佔用1,3,3,8,4個字節的長度。

類型定義 取值範圍 佔用存儲空間
DATE '1000-01'到'9999-12-31' 3個字節
TIME '-838:59:59'到'838:59:59' 3個字節
DATETIME '1000-01-01 00:00:00'到'9999-12-31 23:59:59' 8個字節
TIMESTAMP '1970-01-01 00:00:00'到'2038-01-19 03:14:07' 4個字節
YEAR([M]) 1901到2155 1個字節

DATE,TIME,DATETIME

DATE數據類型表示日期的值,佔用3個字節,其取值範圍爲1000-01-01~9999-12-31,默認零值爲0000-00-00

TIME類型佔用3個字節,其取值範圍是'-838:59:59'到'838:59:59',注意TIME類型並非表示時分秒,而表示逝去的一段時間,即表示兩個事件之間的時間間隔,因此TIME類型能夠爲負值。

當咱們從數據表中查詢TIME類型時,其顯示格式爲:

hh:mm:ss或hhh:mm:ss
複製代碼

當咱們寫入TIME類型字段值的時候,有些要注意的地方:

當咱們寫入11:30時,會被處理爲11:30:00,當咱們寫入1122時,會被處理爲00:11:22。

默認狀況下,位於TIME範圍以外但有效的值將被裁剪到該範圍的最近端點。例如,「-850:00:00」和「 850:00:00」被轉換爲「 -838:59:59」和「 838:59:59」。無效的TIME值將轉換爲「 00:00:00」。請注意,因爲「 00:00:00」自己就是有效的TIME值,所以沒法經過表中存儲的值「 00:00:00」來判斷原始值是否指定爲「 00」: 00:00'或是否無效。

DATETIME數據類型則是DATETIME兩個種數據類型的組合。

TIMESTAMP

TIMESTAMP數據類型是用於保存日期與時間的組合值的,與時區相關,默認是以UTC(世界標準時間)的格式存儲的,其取值範圍是1970-01-01 00:00:002038-01-29 03:14:07,這也是4個字節所能表達的長度,因此TIMESTAMP佔用4個字節,當咱們從數據中查詢TIMESTAMP的數據列,會根據咱們當前的時區自動轉換值。

YEAR

YEAR佔用一個字節,在聲明時,能夠指定一個寬度MM的取值只能是4,即YEAR類型有兩種寫法,YEARYEAR(4),其取值範圍1901~2155

若是咱們只須要存儲年份,並且年份剛在落在YEAR的取值範圍內,那咱們應該使用YEAR類型,由於若是咱們本身存儲一個年份時,至少須要使用SMALLINT類型,這樣會佔用兩個字節,而YEAR只佔用一個字節。

JSON數據類型

MySQL5.7.8版本開始就支持存儲原生的JSON類型的數據,咱們能夠MySQL中存儲JSON對象JSON數組JSON數據並非以字符串的形式存儲,而是使用一種容許快速讀取文本元素的內部二進制格式進行存儲的,在JSON數據列中插入或者更新的時候將會自動驗證JSON文本數據是否正確,未經過驗證的文本將產生一個錯誤信息。

JSON數組是以中括號([])包含起來,並使用逗號隔的列表,其格式以下所示:

["abc", 10, null, true, false]
複製代碼

JSON對象包含多個key-value,使用花括號({})包括起來並用逗號分隔的數據類型,其格式以下所示:

{"k1": "value", "k2": 10}
複製代碼

另外,與BLOBTEXT類型同樣,設置爲JSON類型的字段時不能設置默認值,其默認值只能爲NULL,因此下面的語句是錯誤的:

CREATE TABLE test_json(
    t json NOT NULL DEFAULT ''
);
複製代碼

運行上面的建表語句,MySQL會提示下面所示的錯誤:

ERROR 1101 (42000): BLOB, TEXT, GEOMETRY or JSON column 't' can't have a default value 複製代碼

下面的語句纔是正確的:

CREATE TABLE test_json(
    t json not null
);
複製代碼

JSON類型的存儲長度與LONGBLOBLONGTEXT類型長度相同,固然最大的長度不能超過max_allowed_packet系統變量設置的值。

咱們能夠下面的語句往上面的數據插入數據:

INSERT INTO test_json VALUES('{"key1": "value1", "key2": "value2"}');
複製代碼

除了提供JSON數據類型,MySQL提供了許多能夠操做JSON數據的函數,下面這些函數的說明:

函數 簡介說明
JSON_APPEND() 將數據附加到JSON文檔
JSON_ARRAY() 建立一個JSON數組
JSON_ARRAY_APPEND() 將數據附加到JSON文檔
JSON_ARRAY_INSERT() 插入JSON數組
JSON_CONTAINS() JSON文檔是否在路徑中包含特定對象
JSON_CONTAINS_PATH() JSON文檔是否在路徑中包含任何數據
JSON_DEPTH() JSON文檔的最大深度
JSON_EXTRACT() 從JSON文檔返回數據
JSON_INSERT() 插入一個值到JSON文檔中
JSON_KEYS() 將JSON文檔的key提取爲一個數組
JSON_LENGTH() JSON文檔中的元素數
JSON_MERGE() 合併JSON文檔
JSON_MERGE_PRESERVE() 合併JSON文檔,保留重複的鍵
JSON_OBJECT() 建立一個JSON對象
JSON_PRETTY() 以易於閱讀的格式打印JSON文檔
JSON_QUOTE() 引用JSON文檔
JSON_REMOVE() 從JSON文檔中移除數據
JSON_REPLACE() 替換JSON文檔中的現有值並返回結果
JSON_SEARCH() 查找全部指定值的位置
JSON_SET() 將數據插入JSON文檔
JSON_STORAGE_SIZE() 用於存儲JSON文檔的二進制表示形式的空間
JSON_TYPE() 返回JSON類型:對象或數組
JSON_UNQUOTE() 取消引用JSON值
JSON_VALID() 驗證JSON數據是否有效

JSON函數的簡單示例:

# 判斷JSON類型
mysql> SELECT JSON_TYPE('["a", "b", 1]');
+----------------------------+
| JSON_TYPE('["a", "b", 1]') |
+----------------------------+
| ARRAY                      |
+----------------------------+

# 建立JSON數組
mysql> SELECT JSON_ARRAY('a', 1, NOW());
+----------------------------------------+
| JSON_ARRAY('a', 1, NOW())              |
+----------------------------------------+
| ["a", 1, "2015-07-27 09:43:47.000000"] |
+----------------------------------------+
複製代碼

上面的一些示例比較簡單,對於這些函數的使用,咱們能夠在實際的使用中慢慢探索。

如何選擇數據類型

上面咱們介紹了這麼多種數據類型,那到底應該如何選擇數據類型呢?對於數據類型的選擇,通常仍是要遵循如下幾個原則:

更小的一般更好

數據越小,佔用的空間就越小,查詢的速度也就越快,佔用的內存與CPU就更少,不過也不要所以就錯誤地選擇了更小的數據類型,而致使數據溢出,畢竟在MySQL,修改數據類型是比較麻煩的事情,尤爲是對已經有大量數據的數據表進行數據類型修改。

簡單就好

一樣,也簡單的類型越好,查詢與寫入的速度也就越快。

避免使用NULL

不少的數據類型的默認值就是NULL,因此不少數據列能夠把NULL做爲空值,不過通常狀況下,最好把數據列設置爲NOT NULL,除非你真的須要把數據列設置爲NULL。

由於容許爲NULL的數據列,在索引處理方面複雜,並且須要額外的空間來存儲。

小結

做爲一個成熟的關係型數據庫管理系統,MySQL支持了許多經常使用數據類型,方便咱們根據不一樣的業務進行挑選,對於這些數據類型,咱們沒必要死記硬背,不過在挑選數據類型時,仍是須要對不一樣數據類型的存儲空間長度,默認值,取值範圍有必定的瞭解,才能挑選出最節省空間也最高效的數據類型。


若是你以爲文章不錯,歡迎掃碼關注,你的關注就是我寫做的最大動力

相關文章
相關標籤/搜索