開domain會議時候提到的mysql字符串大小的計算,讓我想到了曾經回答SSC計算oracle字符長度的問題,難道mysql計算不一樣?臨下班時,嘗試了下,終于弄懂了。閑話少敘(= =#)直奔主題吧。
首先說oracle吧,SSC說他存了一個字符串報出系統錯誤,查看log,發現是字符串過長導致。發現字段類型為varchar2(1000),表明可以最多可以存放1000個字節,已經很大了。但是為什么會報長度不夠呢,看他給的字符遠沒有1000那么多。后來發現他給的字符串中有太多的中文頓號,雖然總長度沒有達到1000,但是考慮到一個中文字符占得字節可是雙倍(gbk,utf-8編碼會是三倍),所以建議他將中文頓號改為英文后成功存入。上述聲明表明括號中為字節的長度大小。當然還有一種申明是varchar2(1000 char),這種就表示存放1000個字符。但是這種要特別注意:oracle中字符串類型最大4000字節,所以如果申明這種字符的方式的話,一定要注意不能存太多漢字,否則很容易超出4000字節。所以保險的做法就是varchar2(2000 char),并且是gbk編碼的話,這樣能保證在4000以內。那么mysql是不是也是這樣呢?實驗如下:
我們創建表的時候會給字段指定空間大小。int(1),char(20),varchar(20)等。那么varchar(20)到底是多大呢?20是字符數還是字節數?
用事實說話:
執行結果如下:
結果只有以上三條記錄。三個漢字和兩個漢字帶一個字符的都報出超出column長度。如果是字節數的,我們知道utf8中一個漢字占三個字節,varchar(2)如果表示兩個字節的話,肯定是不能存一個或者兩個漢字的。所以這里面肯定不是指字節數。通過以下查詢:
select name,length(name),char_length(name) from test1;
得出:
從表中可以看出一個漢字占三個字節,一個字符占一個字節。所以varchar中的數字表示字符數,無論是漢字還是字符。但是它的大小取決于存的數。所以會出現同一列的值占的空間大小不一樣,也就是說同樣的字符串列,mysql的值可以達到很大很大但是不會超過[(65535-2)/3]個字節。