MySQL?CHAR和VARCHAR區(qū)別
MYSQL中char和varchar是存儲(chǔ)較短字符串常用的兩種數(shù)據(jù)類型,用法比較相似,需要在使用時(shí)都需要指定長度用來表示表示可以容納的最大字符數(shù)量。雖然這兩種數(shù)據(jù)類型有很多相似之處,但是在數(shù)據(jù)長度、數(shù)據(jù)寫入讀取、存儲(chǔ)引擎存儲(chǔ)上都有比較大的差異。
使用形式
char和varchar的最簡單的使用方式是通過類型后面跟長度,確定該字段最大存儲(chǔ)的字符個(gè)數(shù),舉例如下,創(chuàng)建一張表,表里面兩個(gè)字段分別是CHAR和VARCHAR,設(shè)置的長度是6,也就十說最大存儲(chǔ)的字符個(gè)數(shù)為6:
create table chars(c CHAR(6), vc VARCHAR(6));
簡述中描述過1-2bytes存儲(chǔ)數(shù)據(jù)長度,具體的存儲(chǔ)規(guī)則可以描述如下,這里我們引入三個(gè)符號,分別是列的設(shè)定長度(M),字符集的長度(C),數(shù)據(jù)的實(shí)際長度(L),具體如何存儲(chǔ)長度信息,大體可以描述如下:
如果M * C <= 255,使用1bytes表示長度。
如果M * C > 255,使用兩個(gè)字節(jié)表示長度,但是有下面兩種場景:
- 當(dāng)L <= 127時(shí),也就時(shí)長度可以用 0111111表示時(shí),使用一個(gè)字節(jié)表示長度
- 當(dāng)L > 127 時(shí),使用兩個(gè)字節(jié)表示長度。
差異
char和varchar在聲明形式相似,兩種數(shù)據(jù)類型的差異可以總結(jié)如下:
長度差異
char支持的存儲(chǔ)的最大數(shù)據(jù)長度是0-255,varchar支持存儲(chǔ)的的數(shù)據(jù)范圍0-65535(受限于表行的長度限制65535bytes及相關(guān)字符集)。
char類型測試:
# char創(chuàng)建表 mysql> create table chars_c_256(c CHAR(256)); ERROR 1074 (42000): Column length too big for column 'c' (max = 255); use BLOB or TEXT instead mysql> create table chars_c_0(c CHAR(0)); Query OK, 0 rows affected (0.00 sec) mysql> create table chars_c_1(c CHAR(1)); Query OK, 0 rows affected (0.00 sec) mysql> create table chars_c_255(c CHAR(255)); Query OK, 0 rows affected (0.01 sec)
varchar類型測試:
# 查看mysql server默認(rèn)字符集 show variables like '%character_set_server%'; mysql> show variables like '%character_set_server%'; +----------------------+---------+ | Variable_name ? ? ? ?| Value ? | +----------------------+---------+|? character_set_server | utf8mb4 | +----------------------+---------+ 1 row in set (0.00 sec) # 由于server端使用的字符集是utf8mb4,utf8mb4最大占用4bytes,單行最大字節(jié)數(shù)是65535bytes,因此整行可以完整存儲(chǔ)的最大字符數(shù)16383 # varchar創(chuàng)建表 mysql> create table vchars_c_16384(c VARCHAR(16384)); ERROR 1074 (42000): Column length too big for column 'c' (max = 16383); use BLOB or TEXT instead mysql> create table vchars_c_16383(c VARCHAR(16383)); Query OK, 0 rows affected (0.01 sec) mysql> create table vchars_c_0(c VARCHAR(0)); Query OK, 0 rows affected (0.01 sec)
數(shù)據(jù)寫入讀取差異
使用char和varchar時(shí)需要指定長度,在非嚴(yán)格sql模式下,超過設(shè)定長度的數(shù)據(jù)會(huì)被截?cái)?,并發(fā)出一個(gè)警告,嚴(yán)格模式下超過設(shè)定長度的數(shù)據(jù)會(huì)報(bào)錯(cuò)。于此同時(shí),每一列都會(huì)在行格式中使用1-2bytes用來表示數(shù)據(jù)長度,如果數(shù)據(jù)長度沒有超過255bytes使用一個(gè)字節(jié)表示,如果超過255bytes使用2bytes表示長度。,如果數(shù)據(jù)長度超過設(shè)定長度,那么數(shù)據(jù)會(huì)被截?cái)啵瑖?yán)格sql模式時(shí),sql會(huì)報(bào)錯(cuò),非嚴(yán)格模式時(shí),sql會(huì)警告,如果被截掉的內(nèi)容時(shí)空格char和varchar的表現(xiàn)形式不太一樣,varchar無論在任何sql模式下都會(huì)發(fā)出警告,而char在嚴(yán)格sql模式才會(huì)發(fā)出警告,具體可以測試如下:
# 查看當(dāng)前表模式 mysql> show variables like "sql_mode"; +---------------+-----------------------------------------------------------------------------------------------------------------------+ | Variable_name | Value ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? | +---------------+-----------------------------------------------------------------------------------------------------------------------+| ?sql_mode ? ? ?| ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION | +---------------+-----------------------------------------------------------------------------------------------------------------------+ 1 row in set (0.00 sec) # 可以看到STRICT_TRANS_TABLES模式,為支持事務(wù)性的表開啟嚴(yán)格sql模式,因?yàn)槲疫@邊使用的存儲(chǔ)引擎是innodb,因此會(huì)默認(rèn)開啟嚴(yán)格sql模式 ?# 截?cái)嗫崭竦膱鼍? mysql> insert into chars (c, vc) values('123456 ', '123456'); Query OK, 1 row affected (0.00 sec) mysql> insert into chars (c, vc) values('123456', '123456 '); Query OK, 1 row affected, 1 warning (0.00 sec)? # 截?cái)嘧址膱鼍? mysql> insert into chars (c, vc) values('abcdef', 'abcdefg'); ERROR 1406 (22001): Data too long for column 'vc' at row 1 mysql> insert into chars (c, vc) values('abcdefg', 'abcdef'); ERROR 1406 (22001): Data too long for column 'c' at row 1 # 關(guān)閉嚴(yán)格sql模式 mysql> SET sql_mode = '';Query OK, 0 rows affected (0.00 sec) mysql> show variables like "sql_mode"; +---------------+-------+ | Variable_name | Value | +---------------+-------+ | sql_mode ? ? ?| ? ? ? | +---------------+-------+ 1 row in set (0.00 sec)? # 截?cái)嗫崭竦膱鼍? mysql> insert into chars (c, vc) values('abcdef ', 'abcdef'); Query OK, 1 row affected (0.00 sec) mysql> insert into chars (c, vc) values('abcdef', 'abcdef '); Query OK, 1 row affected, 1 warning (0.00 sec) # 截?cái)嘧址膱鼍? mysql> insert into chars (c, vc) values('abcdef', 'abcdefg'); Query OK, 1 row affected, 1 warning (0.00 sec) mysql> insert into chars (c, vc) values('abcdefg', 'abcdef'); Query OK, 1 row affected, 1 warning (0.00 sec)
char普遍可以理解是固定長度的string,varchar可以是設(shè)定長度內(nèi)的可變長度的string,char在存儲(chǔ)時(shí)如果存儲(chǔ)的數(shù)據(jù)長度不夠設(shè)置長度,會(huì)在后數(shù)據(jù)右邊填充空格,檢索的時(shí)候填充數(shù)據(jù)會(huì)被移除。
varchar在寫入時(shí)如果后面有空格,會(huì)連同空格一塊寫入,如果char后面有空格會(huì)被截?cái)嗟?,具體可以測試如下:
insert into chars (c, vc) values('2 ?', '2 ?'); mysql> select CONCAT('(', c, ')'), CONCAT('(', vc, ')') from chars where c = '2 ?'; Empty set (0.00 sec) mysql> select CONCAT('(', c, ')'), CONCAT('(', vc, ')') from chars where c = '2'; +---------------------+----------------------+|? CONCAT('(', c, ')') | CONCAT('(', vc, ')') | +---------------------+----------------------+| ?(2) ? ? ? ? ? ? ? ? | (2 ?) ? ? ? ? ? ? ? ?| +---------------------+----------------------+ 1 row in set (0.00 sec) mysql> select CONCAT('(', c, ')'), CONCAT('(', vc, ')') from chars where vc = '2'; Empty set (0.00 sec) mysql> select CONCAT('(', c, ')'), CONCAT('(', vc, ')') from chars where vc = '2 ?'; +---------------------+----------------------+ | CONCAT('(', c, ')') | CONCAT('(', vc, ')') | +---------------------+----------------------+ | (2) ? ? ? ? ? ? ? ? | (2 ?) ? ? ? ? ? ? ? ?| +---------------------+----------------------+ 1 row in set (0.00 sec)
存儲(chǔ)引擎存儲(chǔ)差異
由于比較常用的存儲(chǔ)引擎innodb舉例,innodb支持多種行格式,每種行格式對這兩種字符的存儲(chǔ)形式都有細(xì)微差異,具體一一講述。
REDUNDANT(冗余)
CHAR(M)會(huì)分配M個(gè)字符的空間,如果字符集大小不固定,會(huì)按照字符集占用的最大字節(jié)數(shù)計(jì)算需要的存儲(chǔ)空間,如utf8占用的存儲(chǔ)空間是1-3 bytes,CHAR(8)占用的空間就是24 bytes,超出實(shí)際存儲(chǔ)數(shù)據(jù)意外的空間會(huì)填充空格,如CHAR(10)的空間里面只存儲(chǔ)5個(gè)字符,那么剩余空間會(huì)填充空格字符。
VARCHAR(M)會(huì)分配實(shí)際存儲(chǔ)的數(shù)據(jù)的空間,如果 VARCHAR(10)實(shí)際存儲(chǔ)了5個(gè)字符,那么會(huì)分配5個(gè)字符的空間,但如果實(shí)際數(shù)據(jù)后面有空格,不會(huì)被移除。
COMPACT(緊湊)
對于定長字符集,如ascii(1bytes),CHAR(M)會(huì)存儲(chǔ)在一段固定的空間里面,空間內(nèi)長度為 M * 字符集單字符長度
對于可變字符集,如utf8mb3(1-4bytes) and utf8mb4(1-4bytes),CHAR(M)會(huì)自少分配M bytes用來存儲(chǔ)數(shù)據(jù)。但是如果存儲(chǔ)的數(shù)據(jù)超過了M bytes,那么數(shù)據(jù)會(huì)在裁剪掉數(shù)據(jù)尾部空格后,按照數(shù)據(jù)大小分配空間,然后將數(shù)據(jù)存儲(chǔ)在對應(yīng)空間中。
VARCHAR(M)實(shí)際數(shù)據(jù)占用的存儲(chǔ)空間同REDUNDANT(冗余)格式
DYNAMIC(動(dòng)態(tài))
存儲(chǔ)模式同COMPACT(緊湊)模式(數(shù)據(jù)在溢出時(shí)處理方式不同,不再該文檔討論范圍內(nèi))
COMPRESSED(壓縮)
存儲(chǔ)模式同COMPACT(緊湊)模式(數(shù)據(jù)在溢出時(shí)處理方式不同,對溢出數(shù)據(jù)有壓縮,不再該文檔討論范圍內(nèi))
其他MYSQL String類型比較
TEXT 和 BLOD
相同點(diǎn)
- 非嚴(yán)格SQL模式下存儲(chǔ)數(shù)據(jù)時(shí),超過最大長度,都會(huì)發(fā)出警告,在嚴(yán)格SQL模式下,會(huì)報(bào)錯(cuò)。
- TEXT/BLOD可能包含很多數(shù)據(jù),因此當(dāng)TEXT/BOLB列在結(jié)果集中時(shí),會(huì)在臨時(shí)表中處理而不是在內(nèi)存中,因此如果確定不需要TEXT和BLOD應(yīng)該盡量不使用select * from
不同點(diǎn)
- TEXT截?cái)嘟Y(jié)尾空格在任何模式下都會(huì)產(chǎn)生warning,BLOD是二進(jìn)制,沒有空格的概念
- TEXT/BLOD在插入時(shí)都不會(huì)填充任何數(shù)據(jù),在select的時(shí)候不會(huì)剝離任何數(shù)據(jù)
- TEXT上建立索引時(shí),如兩條記錄A 和 'A ',索引比較時(shí)會(huì)忽略尾隨空格,A 和 'A '值是相等的,BLOD值是不同的
到此這篇關(guān)于MySQL CHAR和VARCHAR區(qū)別的文章就介紹到這了,更多相關(guān)MySQL CHAR VARCHAR內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
使用mysql_udf與curl庫完成http_post通信模塊示例
這篇文章主要介紹了使用mysql_udf與curl庫完成http_post通信模塊示例,需要的朋友可以參考下2014-03-03Mysql數(shù)據(jù)庫定時(shí)備份腳本分享
這篇文章主要分享了Mysql數(shù)據(jù)庫的定時(shí)備份腳本,幫助大家更好的理解和使用MySQL數(shù)據(jù)庫,感興趣的朋友可以了解下2020-09-09MySQL獲得當(dāng)前日期時(shí)間函數(shù)示例詳解
這篇文章主要給大家介紹了關(guān)于MySQL獲得當(dāng)前日期時(shí)間函數(shù)的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-12-12MySQL事務(wù)的ACID特性以及并發(fā)問題方案
這篇文章主要介紹了MySQL事務(wù)的ACID特性以及并發(fā)問題方案,文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考一下2022-07-07Ubuntu中遠(yuǎn)程連接Mysql數(shù)據(jù)庫的詳細(xì)圖文教程
Ubuntu是一個(gè)以桌面應(yīng)用為主的Linux發(fā)行版操作系統(tǒng),這篇文章主要為大家詳細(xì)介紹了Ubuntu中遠(yuǎn)程連接Mysql數(shù)據(jù)庫的詳細(xì)圖文教程,有需要的小伙伴可以參考下2025-04-04解決修改mysql的data_dir所引發(fā)的錯(cuò)誤問題
本文給大家分享解決修改mysql的data_dir所引發(fā)的錯(cuò)誤問題,非常不錯(cuò)具有參考借鑒價(jià)值,需要的朋友參考下吧2017-04-04