MySQL中除了數(shù)值類型外疼邀,另一個用的比較多的就是字符類型了丁鹉。字符類型有很多不同種類:VARCHAR
,CHAR
,BLOB
,TEXT
VARCHAR
VARCHAR是變長的字符類型妒潭,實際的存儲格式如下圖所示:
VARCHAR類型由prefix
和data
組成,其中prefix
由一個或者兩個字節(jié)構(gòu)成揣钦,作用是指定data
的長度雳灾。如果data
的長度小于等于255,則prefix
只需要一個字節(jié)冯凹,因為一個字節(jié)可表示的最大的無符號數(shù)就是255谎亩,如果data
的長度大于255炒嘲,則prefix
需要用兩個字節(jié)表示,而兩個字節(jié)可表示的最大的無符號數(shù)是65535匈庭,由此可知VARCHAR最大可以存儲65535個字符夫凸。
CHAR
CHAR是定長的字符類型,實際的存儲格式如下圖所示:
和VARCHAR不同的是阱持,CHAR中只存儲實際的內(nèi)容夭拌,沒有用來指定長度的prefix
,并且CHAR最大可存儲的字符數(shù)是255衷咽。假設(shè)一個CHAR(5)的字段鸽扁,存儲的內(nèi)容只有4個字符,那么實際存儲時會在最后加上1個空格來補齊至5個字符镶骗。而在查詢時桶现,返回的結(jié)果中末尾的空格將被移除,除非開啟了PAD_CHAR_TO_FULL_LENGTH
模式鼎姊。
一個CHAR(5)的字段骡和,分配了5個字符的空間,如下圖所示:
當(dāng)插入了abcd
之后相寇,實際存儲的內(nèi)容如下圖所示:
當(dāng)實際存儲的字符長度不足時慰于,MySQL會在末尾用空格補足。
而查詢時裆赵,實際返回的內(nèi)容中,末尾的空格又是被移除的跺嗽,如下圖所示:
用一個實際的例子演示一下:
- 1战授、準(zhǔn)備一張表
create table `test_c` (
a char(5) not null,
b varchar(5) not null
) engine=InnoDB;
- 2、插入幾條測試數(shù)據(jù)
insert into test_c (a,b)
values
('abcd','abcd'),
('abcd ','abcd '),
(' abcd',' abcd');
- 3桨嫁、查詢結(jié)果
select concat("'",a,"'") as a,concat("'",b,"'") as b from test_c;
- 4植兰、結(jié)果如下
+---------+---------+
| a | b |
+---------+---------+
| 'abcd' | 'abcd' |
| 'abcd' | 'abcd ' |
| ' abcd' | ' abcd' |
+---------+---------+
可以發(fā)現(xiàn)查詢時,返回的結(jié)果中末尾的空格都被移除了璃吧,不管末尾的空格是不是我們實際存儲的值楣导。那這種情況下就會出現(xiàn)問題,實際我們是需要末尾的空格的畜挨,但查詢的結(jié)果末尾的空格被移除了筒繁。解決的方法是,開啟PAD_CHAR_TO_FULL_LENGTH
的SQL Mode巴元。
- 1毡咏、先查一下當(dāng)前的SQL Mode:
select @@sql_mode;
結(jié)果如下:
+--------------------------------------------+
| @@sql_mode |
+--------------------------------------------+
| STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION |
+--------------------------------------------+
- 2、設(shè)置SQL Mode:
SET sql_mode=`PAD_CHAR_TO_FULL_LENGTH`;
- 3逮刨、再查詢結(jié)果:
select concat("'",a,"'") as a,concat("'",b,"'") as b from test_c;
- 4呕缭、結(jié)果如下:
+---------+---------+
| a | b |
+---------+---------+
| 'abcd ' | 'abcd' |
| 'abcd ' | 'abcd ' |
| ' abcd' | ' abcd' |
+---------+---------+
可以看到,設(shè)置了PAD_CHAR_TO_FULL_LENGTH的SQL Mode之后,CHAR類型的字段末尾的空格沒有被移除恢总。
存儲的長度超限
當(dāng)存儲的字符長度超過了CHAR和VARCHAR設(shè)置的長度迎罗,在不同的情況下會有不同的效果。在嚴(yán)格模式下片仿,超過長度的字符是不能保存成功的纹安,系統(tǒng)會報錯。在非嚴(yán)格模式下滋戳,能保存成功钻蔑,CHAR類型的會截斷超過長度的部分,并且不會有任何反映奸鸯,VARCHAR類型的也會截斷超過長度的部分咪笑,但是會拋出警告。
PS:
需要注意的是娄涩,CHAR和VARCHAR中存儲的內(nèi)容的長度是指的字符長度窗怒,不是字節(jié)長度,而字符長度跟選擇的字符集有關(guān)蓄拣,比如ASCII字符集可以存儲英文和數(shù)字等扬虚,不能存儲中文,因為一個中文字符占3個字節(jié)球恤,UTF8字符集就可以存儲中文了辜昵,但是UTF8不能存儲emoji表情,因為emoji表情占4個字節(jié)咽斧,而UTF8MB4就可以存儲emoji表情堪置。
CHAR和VARCHAR的區(qū)別:
比較維度 | CHAR | VARCHAR |
---|---|---|
組成結(jié)構(gòu) | data | prefix+data |
最低存儲需求 | 0字節(jié) | 1字節(jié) |
最大長度 | 255 | 65535 |
存儲時長度不足 | 末尾用空格補齊 | 不補齊 |
存儲時長度超限(非嚴(yán)格模式) | 截斷并且靜默 | 截斷并且警告 |
存儲時長度超限(嚴(yán)格模式) | 報錯并且不能保存 | 報錯并且不能保存 |
查詢時(無PAD_CHAR_TO_FULL_LENGTH) | 移除末尾空格 | 不移除末尾空格 |
查詢時(有PAD_CHAR_TO_FULL_LENGTH) | 不移除末尾空格 | 不移除末尾空格 |
BLOB和TEXT
BLOB和TEXT主要是用來存儲數(shù)據(jù)長度非常大的字符類型的,BLOB主要是存儲二進制字符類型张惹,TEXT則是存儲字符串舀锨。
其中BLOB又包括了TINYBLOB
,SMALLBLOB
,MEDIUNBLOB
,LONGBLOB
,TEXT包括了TINYTEXT
,SMALLTEXT
,MEDIUNTEXT
,LONGTEXTB
。
當(dāng)BLOB和TEXT的值太大時宛逗,InnoDB會使用專門的外部
存儲區(qū)域來存儲坎匿,這時就會在字段中用一個1~4個字節(jié)的指針,紀(jì)錄下外部
實際存儲的區(qū)域雷激。
MySQL對BLOB和TEXT類型的字段進行排序時替蔬,只會對字段的前max_sort_length
個字節(jié)的內(nèi)容而不是整個內(nèi)容進行排序。
我是逅弈屎暇,如果文章對您有幫助进栽,歡迎您點贊加關(guān)注,并歡迎您關(guān)注我的公眾號: