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