原創做者,公衆號【程序員讀書】,歡迎關注公衆號,轉載文章請註明出處哦。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
支持的數據類型有:數字類型
,字符串類型
(包括字符)、時間與日期類型
、空間類型
和JSON類型
,不一樣數據類型有不一樣的特性,咱們可從該類型的存儲空間、取值範圍、默認值、如何進行比較,是否能夠索引等等方面對其進行學習。bash
注:空間數據類型在平時使用並不太經常使用,所以在咱們的文章中便不做介紹了。函數
MySQL
的數字類型可分爲整數類型
、定點型類型
、浮點數類型
、位類型
四種類型,下面表格是這四種數據類型的更細緻劃分,咱們能夠從表格中對全部數字類型有必定的瞭解。學習
數據類型定義 | 存儲空間佔用量 | 取值範圍 |
---|---|---|
TINYINT[(M)] | 1個字節 | 帶符號:-128~127(-2到2-1) 無符號:0~255(2-1) |
SMALLINT[(M)] | 2個字節 | 帶符號:-32768~32767(-2到2-1) 無符號:0~65535(2-1) |
MEDIUMINT[(M)] | 3個字節 | 帶符號:-8388608~8388607(-2到2-1) 無符號:0~16777215(2-1) |
INT[(M)] | 4個字節 | 帶符號:-2147683648~2147683647(-2到2-1) 無符號:0~4294967295(2-1) |
BIGINT[(M)] | 8個字節 | 帶符號:-128~127 無符號:0~255 |
DECIMAL([M[,D]]) | 可變長度 | 其取值範圍由M和D的值決定 |
FLOAT[(M)] | 4個字節 | 最小非零值 : 1.175494351E-38 最大非零值: 1.175494351E-38 |
DOUBLE[(M)] | 8個字節 | 最小非零值 : 1.175494351E-38 最大非零值: 1.175494351E-38 |
BIT[(M)] | 1~4個字節 | 0到2-1 |
整數類型用於存儲整數,根據其存儲的字節大小可分爲TINYINT
,SMALLINT
,MEDIUMINT
,INT
,BIGINT
,分別佔用1,2,3,4,8個字節的大小,存儲範圍從 -2到2-1,其中N是類型的存儲空間的位數(bit,1個字節8bit)。spa
通常整數都支持正負值,不過可使用可選的屬性UNSIGNED
,使其不容許負值,這樣的話,可使用存儲的正數上限提升一倍,好比TINYINT
的範圍由-128~127
變爲0~255
。
CREATE TABLE test_int(
id int unsigned not null
);
複製代碼
對整數類型,在建立數據表時,能夠指定AUTO_INCRMENT
屬性,讓該字段能夠變成一個能夠自動增加的序列,如:
CREATE TABLE test_int(
id INT UNSIGNED NOT NULL AUTO_INCRMENT PRIMARY KEY,
name VARCHAR(32) NOT NULL
);
複製代碼
實數類型分爲浮點數
和定點數
類型兩種,定點數類型一種是精確值類型,DECIMAL
就是定點數類型,浮點數是一種是近似值類型,FLOAT
和DOUBLE
就是浮點數類型。
浮點數類型存四捨五入的問題,所以在有須要精確運算的時候,可使用定點數或整數數據,避免計算偏差。
浮點數也可使用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-1個字節 | L+1個字節 |
BLOB | 2-1個字節 | L+2個字節 |
MEDIUMBLOB | 2-1個字節 | L+3個字節 |
LONGBLOB | 2-1個字節 | L+4個字節 |
TINYTEXT | 2-1個字符 | L+1個字節 |
TEXT] | 2-1個字符 | L+2個字節 |
MEDIUMBLOB | 2-1個字符 | L+3個字節 |
LONGTEXT | 2-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
在於,CHAR
是定長字符串數據類型,而VARCHAR
是可變長度的字符串數據類型。
CHAR
的長度取值範圍是1~255
,默認值1,但CHAR(0)是合法,佔用1個位,表示空字符串。
而VARCHAR
的取值範圍是1~65535,不過VARCHAR的最大長度通常小於65535,所以MySQL
中數據行的最大長度也是65535,況且VARCHAR
還須要額外兩個字節來記錄其目前的存儲長度。
BINARY
與VARBINARY
的區別與CHAR
和VARCHAR
的區別是相似的。
BLOB
是包含TINYBLOB
,BLOB
,MEDIUMBLOB
,LONGBLOB
系列數據類型的家族,用於存儲二進制字符串,好比圖片、聲音等數據,而TEXT
是包含TINYTEXT
,TEXT
,MEDIUMTEXT
,LONGTEXT
系列數據類型的家族用於存儲非二進制字符串,因此TEXT
系列的類型存儲與解析與字符集有關。
使用MEMORY
存儲引擎的數據表不支持BLOB
和TEXT
這兩種數據類型。
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
爲存儲時間與日期提供了YEAR
,DATE
,TIME
,DATETIME
,TIMESTAMP
等數據類型,分別佔用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
數據類型表示日期的值,佔用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
數據類型則是DATE
和TIME
兩個種數據類型的組合。
TIMESTAMP數據類型是用於保存日期與時間的組合值的,與時區相關,默認是以UTC
(世界標準時間)的格式存儲的,其取值範圍是1970-01-01 00:00:00
到2038-01-29 03:14:07
,這也是4個字節所能表達的長度,因此TIMESTAMP
佔用4個字節,當咱們從數據中查詢TIMESTAMP
的數據列,會根據咱們當前的時區自動轉換值。
YEAR
佔用一個字節,在聲明時,能夠指定一個寬度M
,M
的取值只能是4,即YEAR
類型有兩種寫法,YEAR
和YEAR(4)
,其取值範圍1901~2155
若是咱們只須要存儲年份,並且年份剛在落在YEAR
的取值範圍內,那咱們應該使用YEAR
類型,由於若是咱們本身存儲一個年份時,至少須要使用SMALLINT
類型,這樣會佔用兩個字節,而YEAR
只佔用一個字節。
MySQL
從5.7.8
版本開始就支持存儲原生的JSON
類型的數據,咱們能夠MySQL
中存儲JSON對象
或JSON數組
。JSON
數據並非以字符串的形式存儲,而是使用一種容許快速讀取文本元素的內部二進制格式進行存儲的,在JSON數據列
中插入或者更新的時候將會自動驗證JSON
文本數據是否正確,未經過驗證的文本將產生一個錯誤信息。
JSON數組是以中括號([]
)包含起來,並使用逗號隔的列表,其格式以下所示:
["abc", 10, null, true, false]
複製代碼
JSON對象包含多個key-value,使用花括號({}
)包括起來並用逗號分隔的數據類型,其格式以下所示:
{"k1": "value", "k2": 10}
複製代碼
另外,與BLOB
和TEXT
類型同樣,設置爲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類型
的存儲長度與LONGBLOB
,LONGTEXT
類型長度相同,固然最大的長度不能超過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做爲空值,不過通常狀況下,最好把數據列設置爲NOT NULL,除非你真的須要把數據列設置爲NULL。
由於容許爲NULL的數據列,在索引處理方面複雜,並且須要額外的空間來存儲。
做爲一個成熟的關係型數據庫管理系統,MySQL
支持了許多經常使用數據類型,方便咱們根據不一樣的業務進行挑選,對於這些數據類型,咱們沒必要死記硬背,不過在挑選數據類型時,仍是須要對不一樣數據類型的存儲空間長度,默認值,取值範圍有必定的瞭解,才能挑選出最節省空間也最高效的數據類型。
若是你以爲文章不錯,歡迎掃碼關注,你的關注就是我寫做的最大動力