varchar(100)
先說結(jié)論,mysql 中的 varchar 是有最大長度限制的,這個值是 65535 個字節(jié)。
varchar(100),這個 100 的單位是啥,這個單位其實在不同版本中是不一樣的。
在早期低版本中代表的是字節(jié),具體哪個版本我也沒去驗證了,后來被改成了字符,不過可以肯定的是在 5.1 版本后, varchar(100) 就是指 100 個字符。
說到 varchar ,一般都會拿 char 來做比較說明。
char 是固定長度,其單位也是字符,比如 char(10),就表示不管你給的什么值,都會被 mysql 固定保存成 10 個字符。
如果給的字符長度小于 10,那么在尾部就會自動用空格補齊。
如果大于 10,在嚴(yán)格模式(strict sql mode)下就會報錯,在非嚴(yán)格模式下就會對內(nèi)容做自動截取操作。
另外 char 也是有最大長度限制的,最大長度為 255, 即 char 類型最多只能保存 255 個字符,char(256) 這都是錯誤的寫法,可以看下面的例子。
##創(chuàng)建一個表,同時聲明address字段長度為256會報錯,最大為255
mysql> create table test2 ( address char(256) ); ERROR 1074 (42000): Column length too big for column 'address' (max = 255); use BLOB or TEXT instead
下面是 char 和 varchar 對于同一個字符所需要的不同的存儲空間,這里假設(shè)使用的是 latin1 單字節(jié)字符集。
|
值 |
CHAR(4) |
存儲空間大?。ㄗ止?jié)) |
VARCHAR(4) |
存儲空間大小(字節(jié)) |
|---|---|---|---|---|
|
'' |
' ' |
4 bytes |
'' |
1 byte |
|
'ab' |
'ab ' |
4 bytes |
'ab' |
3 bytes |
|
'abcd' |
'abcd' |
4 bytes |
'abcd' |
5 bytes |
|
'abcdef' |
'abcd' |
4 bytes |
'abcd' |
5 bytes |
細心的你可能會發(fā)現(xiàn) varchar 的存儲空間會比字符的實際長度多 1 個字節(jié),這是因為 varchar 需要額外增加 1 到 2 個字節(jié)來存儲字符的長度,這個值被稱作前綴。
也就是說在 varchar 類型中,除了字符本身實際占用的空間外,還需要 1 個或 2 個字節(jié)來聲明這個字符的長度。
如果存儲的值小于 255 個字節(jié),則使用 1 個字節(jié)來存儲前綴,如果大于 255 個字節(jié)則使用 2 個字節(jié)來存儲前綴。
關(guān)于字符集和字節(jié)的關(guān)系,以及字節(jié) (byte) 與位 (bit) 的關(guān)系。
1 byte (字節(jié)) = 8 bit (位) 2^8 = 256 所以計算機里常見的 255、256 臨界值絕大多數(shù)與這個有關(guān) 1 個字節(jié)具體占多大的空間,這與所使用的字符集有關(guān)系 比如 latin1 單字節(jié)字符集,1 個字符即占 1 個字節(jié) 我們常見的 GBK、UTF8、UTF8-MB4 這些都是多字節(jié)字符集
GBK :一個字符最多占 2 個字節(jié) UTF8:一個字符最多占 3 個字節(jié) UTF8MB4:一個字符最多占 4 個字節(jié)
好了,再堅持一會,回到文章開頭的問題,為啥 varchar 最大長度是 65535 個字節(jié)呢,其實這個是受 mysql 另一個規(guī)則限制導(dǎo)致的,mysql 規(guī)定了每行數(shù)據(jù)大小不能超過 65535 個字節(jié)。
另外還有一個小問題,一個字段如果允許為 null ,在 mysql 中也是需要增加額外空間來單獨標(biāo)識的,反之則不需要這個額外空間,至于這個空間大小具體是怎么計算的,我目前也還沒有研究過。
結(jié)合上面說的幾點,下面來通過幾個實例來驗證下。
##字符集設(shè)置為latin1,1個字符=1個字節(jié),字段允許為null mysql> create table test ( address varchar(65536) default null ) charset=latin1; ERROR 1074 (42000): Column length too big for column 'address' (max = 65535); use BLOB or TEXT instead ##減去varchar前綴長度標(biāo)識2個字節(jié),還是報錯,說明null標(biāo)識也占用了空間 mysql> create table test ( address varchar(65533) default null ) charset=latin1; 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 ##把字段設(shè)置為非空即可建表成功 mysql> create table test ( address varchar(65533) not null ) charset=latin1; Query OK, 0 rows affected (0.01 sec) ##如果字符集設(shè)置為UTF8,那么 max=65535/3=21845,一個字符最多占3個字節(jié) mysql> create table test2 ( address varchar(65533) not null ) charset=UTF8; ERROR 1074 (42000): Column length too big for column 'address' (max = 21845); use BLOB or TEXT instead
基于上面幾個實例,基本上可以得出計算 varchar 最大長度限制的公式。
varchar 最大長度限制 = (行最大字節(jié)數(shù)(65535) - null 標(biāo)識字節(jié)數(shù) - 長度前綴字節(jié)數(shù)(1或2)) / 字符集單字符占用最多字節(jié)數(shù)
看到這里,不知道你有沒有一個疑問,為什么長度前綴 1 或 2 個字節(jié)就夠用了呢,因為 2 個字節(jié)的話,2^16 = 65536,這已經(jīng)超過 mysql 行最大字節(jié)數(shù) 65535 的限制了,所以 1 到 2 個字節(jié)就夠用了。
最后再看一個綜合例子,我們創(chuàng)建一個表,采用 UTF8 字符集,添加兩個非空字段,分別為 char 和 varchar 類型,char 類型長度給定為 255。
那么 varchar 類型字段的最大字節(jié)數(shù)應(yīng)該就是,
65535 (行最大字節(jié)數(shù)) - 255*3 (一個字符最多占 3 個字節(jié)) = 64770, 然后再減去 2 個長度前綴字節(jié), 64770 - 2 = 64768, 最后再算出 varchar 最大字符數(shù)為 64768 / 3 = 21589.33, ##字符數(shù)21590超過最大字符數(shù)會報錯 mysql> create table test4 (name char(255) not null, address varchar(21590) not null ) charset=utf8; 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 ##字符數(shù)21589則剛好能創(chuàng)建成功 mysql> create table test4 (name char(255) not null, address varchar(21589) not null ) charset=utf8; Query OK, 0 rows affected, 1 warning (0.02 sec)
好了,關(guān)于 varchar 的最大長度問題就聊到這了,文中如有錯誤,歡迎大家批評指出,更歡迎大家交流討論,如果文章對你有幫助,點個在看表示對我的支持哈,感謝。
一、首先創(chuàng)建表。
CREATE TABLE `t1` (
`id` int(11) DEFAULT NULL,
`a` char(255) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8
二、插入數(shù)據(jù)。分別插入了250個漢字‘頂’,250個漢字‘頂’和‘12345’,255個漢字‘頂’。字符集是utf8,那么每個漢字占用3字節(jié),每個數(shù)字或英文字符占用1字節(jié)。但是不能插入超出255個字符,否則報錯。
INSERT INTO t1 VALUES (1,'頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂');
INSERT INTO t1 VALUES (2,'頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂12345');
INSERT INTO t1 VALUES (3,'頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂頂');
三、查詢字符數(shù)和字節(jié)數(shù)。
select char_length(a),length(a) from t1;
四、定義表t2,定義char(10)。如果插入數(shù)據(jù)超過10個字符,那么同樣會報錯,而不是截取10個字符。
五、
總結(jié)
以上是生活随笔為你收集整理的varchar(100)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 我去年买了个表是什么意思(网络我去年买了
- 下一篇: 迈克·华莱士比西方记者跑得快!