前言: mysql
前面寫過一篇介紹int類型的文章,一直想寫一篇介紹字符串字段類型的文章,一直拖着也沒思路要怎麼下手。最近多關注了下這方面的文章,決定仍是把拖了很久的文章告終了吧。本篇文章主要會介紹字符串類型char及varchar的用法及區別。sql
本文實驗環境爲MySQL 5.7.23版本,存儲引擎爲Innodb,sql_mode採用嚴格模式,字符集是utf8。數據庫
咱們平時使用char類型定義字段時,每每會指定其長度M,即char(M)。其實M指的是字符數,即這個字段最多存儲多少個字符,M可不指定,默認爲1,範圍是[0,255],單個字母、數字、中文等都是佔用一個字符。utf8字符集下一個中文字符佔用3個字節。下面咱們簡單測試下:ide
# 假設以以下建表語句建立測試表 CREATE TABLE `char_tb1` ( `col1` char DEFAULT NULL, `col2` char(5) DEFAULT NULL, `col3` char(10) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8; # 進入數據庫查詢建表語句以下 發現char(M) M可不指定,默認爲1 mysql> show create table char_tb1\G *************************** 1. row *************************** Table: char_tb1 Create Table: CREATE TABLE `char_tb1` ( `col1` char(1) DEFAULT NULL, `col2` char(5) DEFAULT NULL, `col3` char(10) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8 1 row in set (0.00 sec) # 插入數據 能夠看出M表示保存的最大字符數,字母、數字、中文等都是佔用一個字符 mysql> insert into char_tb1 (col1) values ('a'),('1'),('王'),(']'); Query OK, 4 rows affected (0.01 sec) mysql> insert into char_tb1 (col1) values ('aa'),('12'); ERROR 1406 (22001): Data too long for column 'col1' at row 1 mysql> select * from char_tb1; +------+------+------+ | col1 | col2 | col3 | +------+------+------+ | a | NULL | NULL | | 1 | NULL | NULL | | 王 | NULL | NULL | | ] | NULL | NULL | +------+------+------+ 4 rows in set (0.00 sec) mysql> insert into char_tb1 (col2) values ('abcd'),('王-123'),('^*123'),('12'),('一二三四五'); Query OK, 5 rows affected (0.01 sec) mysql> insert into char_tb1 (col2) values ('abcdef'); ERROR 1406 (22001): Data too long for column 'col2' at row 1 mysql> select * from char_tb1; +------+-----------------+------+ | col1 | col2 | col3 | +------+-----------------+------+ | a | NULL | NULL | | 1 | NULL | NULL | | 王 | NULL | NULL | | ] | NULL | NULL | | NULL | abcd | NULL | | NULL | 王-123 | NULL | | NULL | ^*123 | NULL | | NULL | 12 | NULL | | NULL | 一二三四五 | NULL | +------+-----------------+------+ 9 rows in set (0.00 sec) # 下面測試發現M的範圍是[0,255] mysql> alter table char_tb1 add column col4 char(0); Query OK, 0 rows affected (0.10 sec) Records: 0 Duplicates: 0 Warnings: 0 mysql> alter table char_tb1 add column col5 char(255); Query OK, 0 rows affected (0.11 sec) Records: 0 Duplicates: 0 Warnings: 0 mysql> alter table char_tb1 add column col5 char(256); ERROR 1074 (42000): Column length too big for column 'col5' (max = 255); use BLOB or TEXT instead
一樣的,varchar(M)中的的M表示保存的最大字符數,單個字母、數字、中文等都是佔用一個字符。varchar可存儲的長度範圍爲0-65535字節,此外,varchar須要使用1或者2個額外字節記錄字符串的長度:若是列的最大長度小於或等於255字節,則只使用1個字節表示,不然使用2個字節。對於Innodb引擎,utf8字符集來講,單箇中文字符佔用3個字節,因此varchar(M)中的M最大不會超過21845,即M的範圍是[0,21845),而且M必須指定。另外MySQL規定:單個字段長度不大於65535字節;單行最大限制爲65535,這裏不包括TEXT、BLOB字段。即單張表中的全部varchar字段定義的長度之和不能大於65535,因此並非全部varchar(M)字段中的M均可以取到21844,下面咱們來驗證下:測試
# 假設以以下建表語句建立測試表 CREATE TABLE `varchar_tb1` ( `col1` varchar(0) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8; # 查看建表語句 增長字段 發現M必須指定 mysql> show create table varchar_tb1\G *************************** 1. row *************************** Table: varchar_tb1 Create Table: CREATE TABLE `varchar_tb1` ( `col1` varchar(0) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8 1 row in set (0.00 sec) mysql> alter table varchar_tb1 add column col2 varchar; ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '' at line 1 # 下面測試證實M最大可取到21844 mysql> CREATE TABLE `varchar_tb2` (col1 varchar(21844)); Query OK, 0 rows affected (0.04 sec) mysql> CREATE TABLE `varchar_tb3` (col1 varchar(218445)); ERROR 1074 (42000): Column length too big for column 'col1' (max = 21845); use BLOB or TEXT instead # 下面測試證實單行最大限制爲65535字節 mysql> CREATE TABLE `varchar_tb3` (col1 varchar(10)); Query OK, 0 rows affected (0.04 sec) mysql> alter table varchar_tb3 add column col2 varchar(21844); ERROR 1118 (42000): Row size too large. The maximum row size for the used table type, not counting BLOBs, is 65535. This includes storage overhead, check the manual. You have to change some columns to TEXT or BLOBs mysql> alter table varchar_tb3 add column col2 varchar(21834); ERROR 1118 (42000): Row size too large. The maximum row size for the used table type, not counting BLOBs, is 65535. This includes storage overhead, check the manual. You have to change some columns to TEXT or BLOBs mysql> alter table varchar_tb3 add column col2 varchar(21833); Query OK, 0 rows affected (0.09 sec) Records: 0 Duplicates: 0 Warnings: 0 mysql> show create table varchar_tb3\G *************************** 1. row *************************** Table: varchar_tb3 Create Table: CREATE TABLE `varchar_tb3` ( `col1` varchar(10) DEFAULT NULL, `col2` varchar(21833) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8 1 row in set (0.00 sec)
CHAR類型是定長的,MySQL老是根據定義的字符串長度分配足夠的空間。當保存CHAR值時,在它們的右邊填充空格以達到指定的長度,當檢索到CHAR值時,尾部的空格被刪除掉。code
VARCHAR類型用於存儲可變長字符串,存儲時,若是字符沒有達到定義的位數,也不會在後面補空格。可是,因爲行是變長的,在UPDATE時可能使行變得比原來更長,這就致使須要作額外的工做。若是一個行佔用的空間增加,而且在頁內沒有更多的空間能夠存儲,在這種狀況下InnoDB須要分裂頁來使行能夠放進頁內,這樣會增長碎片。server
下面簡單總結下CHAR與VARCHAR字段類型的適用場景:內存
CHAR適合存儲很短的字符串,或者全部值都接近同一個長度。例如,CHAR很是適合存儲密碼的MD5值,由於這是一個定長的值。對於常常變動的數據,CHAR也比VARCHAR更好,由於定長的CHAR類型不容易產生碎片。對於很是短的列,CHAR比VARCHAR在存儲空間上也更有效率。例如用CHAR(1)來存儲只有Y和N的值,若是採用單字節字符集只須要一個字節,可是VARCHAR(1)卻須要兩個字節,由於還有一個記錄長度的額外字節。字符串
下面這些狀況下使用VARCHAR是合適的:字符串很長或者所要存儲的字符串長短不一,差異很大;字符串列的最大長度比平均長度大得多;列的更新不多,因此碎片不是問題。it
額外說明下,咱們在定義字段最大長度時應該按需分配,提早作好預估。特別是對於VARCHAR字段,有人認爲反正VARCHAR數據類型是根據實際的須要來分配長度的,還不如給大一點呢。但事實不是這樣的,好比如今須要存儲一個地址信息,根據評估,只要使用100個字符就能夠了,咱們可使用VARCHAR(100)或VARCHAR(200)來存儲,雖然它們用來存儲90個字符的數據,其存儲空間相同,可是對於內存的消耗是不一樣的。更長的列會消耗更多的內存,由於MySQL一般會分配固定大小的內存塊來保存內部值,尤爲是使用內存臨時表進行排列或者操做時會特別糟糕。因此咱們在分配VARCHAR數據類型時仍然不可以太過於慷慨。仍是要評估實際須要的長度,而後選擇一個最長的字段來設置字符長度。若是爲了考慮冗餘,能夠留10%左右的字符長度。千萬不能認爲VARCHAR是根據實際長度來分配存儲空間,而隨意的分配長度,或者說乾脆使用最大的字符長度。
總結:
本文分別介紹了CHAR與VARCHAR字段類型的使用方法,而且給出了兩者的對比以及適用場景。在實際生產狀況,須要具體狀況具體分析,合適的纔是最好的,但願這篇文章能給到你們參考。