MySQL中CHAR和VARCHAR區別

Code1667發表於2020-12-09

以下都是基於mysql5.0以上版本而言,也就是char和varchar括號內指定的都是最大字元數,話不多說先上結論:

行為char欄位varchar欄位
最大長度255字元括號中最大的字元數通過編碼來算,不超過行65535個位元組
是否定長定長,不足的部分用隱藏空格填充不定長,保留實際字元
空間使用可能浪費更加節省
查詢效率
尾部空格插入時省略插入時不會省略,查詢時可省略
like查詢語句中like後的’ '不會省語句中like後的’ '不會省,欄位結尾的空格也不會省

以上都是指嚴格模式下的情況,如果修改為寬鬆模式,插入時超過指定最大字元數會擷取然後插入。具體改變寬鬆模式看:mysql修改sql_mode為寬鬆模式https://www.cnblogs.com/ningjiabing/p/12795338.html

測試

測試一下是不是如結論,所說尾部空格,包括:長度檢視、尾部空格、查詢的測試

建立表tset_char_varchar

-----------建表------------
CREATE TABLE tset_char_varchar
(
    id       int PRIMARY KEY,
    _char    CHAR(10)    DEFAULT NULL,
    _varchar varchar(10) DEFAULT NULL
) ENGINE = InnoDB
  DEFAULT CHARSET = utf8mb4 COMMENT ='測試char和varchar區別表';
TRUNCATE tset_char_varchar;


-----------插入-------------
INSERT INTO
    tset_char_varchar VALUE
    (1, '123456', '123456'),
    (2, '0123456789', '0123456789'),
    (3, '一二三四五六七八九十', '一二三四五六七八九十');

-----------查詢-------------
SELECT
    _char,
    CHAR_LENGTH(_char) char字元數,
    LENGTH(_char)      char位元組數,
    _varchar,
    CHAR_LENGTH(_varchar) varchar字元數,
    LENGTH(_varchar)      varchar位元組數
FROM
    tset_char_varchar;

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片儲存下來直接上傳(img-LGIvpGKL-1607477835313)(MySQL中char和varchar區別.assets/image-20201208170450416.png)]

從上圖可以看到插入不足10個字元、10個數字、十個漢字所對應的字元數和子節數,在這裡還沒看出差別。(當然如果插入的字元數>10會報錯)

接下來測試一下帶空格的資料

---為了檢視方便把以上資料刪除--
TRUNCATE tset_char_varchar;

-------插入資料------
INSERT INTO
    tset_char_varchar
VALUES
    (1, 'a', 'a'),
    (2,' a',' a'),
    (3,'a ','a '),
    (4,' a ',' a ');

1為不帶空格,2為左邊帶空格,3為右邊帶空格,4為兩邊都帶空格

插入之後檢視查詢結果:

SELECT
    _char,
    CHAR_LENGTH(_char)    char字元數,
    LENGTH(_char)         char位元組數,
    _varchar,
    CHAR_LENGTH(_varchar) varchar字元數,
    LENGTH(_varchar)      varchar位元組數
FROM
    tset_char_varchar;

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片儲存下來直接上傳(img-SCnyfE0H-1607477835316)(MySQL中char和varchar區別.assets/image-20201208171434273.png)]

看第3、4條資料的字元數和位元組數出現了不一致。

id=3儲存的是隻有右邊有空格,那麼varchar把空格保留下來了,可以推斷出id=4這條資料char中缺失的就是右邊空格所佔的位元組,如果不信的話,下面進行驗證。

測試查詢帶空格的資料

  1. 查詢_char不帶空格的結果:
SELECT * FROM tset_char_varchar WHERE _char = 'a';

  1. 查詢_char左側空格的結果:
SELECT * FROM tset_char_varchar WHERE _char = ' a';

  1. 查詢_char右側空格的結果:
SELECT * FROM tset_char_varchar WHERE _char = 'a ';

結果什麼都沒有!

  1. 查詢查詢_char兩側空格的結果:
SELECT * FROM tset_char_varchar WHERE _char = ' a ';	

結果什麼都沒有!

  1. 查詢查詢_varchar結果:
SELECT * FROM tset_char_varchar WHERE _varchar = 'a ';	
SELECT * FROM tset_char_varchar WHERE _varchar = ' a';
SELECT * FROM tset_char_varchar WHERE _varchar = 'a ';
SELECT * FROM tset_char_varchar WHERE _varchar = ' a ';

具體圖片不做贅述,這裡每一條都只能查到唯一一條資料。


【結論】:char方式插入,右邊有空格會自動過濾掉!!

另附常用字符集

以一個字元為例:

字元編碼英文字母(單位:byte)中文漢字(單位:byte)
ISO-8859-111
GB231212
GBK12
UTF-813
UTF-1644

UTF-8字元編碼的優勢非常明顯, 英文和數字(也就是ASCII字符集)只用一個byte, 而歐洲語言比如希臘語的字元佔用2個byte,中文佔用3個byte(超大字符集漢字佔4個byte)。為了世界通用,所以後來像tomcat 8.x IDE等該用utf-8作為預設編碼,也可以顯示中文字元。

參考

Mysql中char和varchar的區別:https://blog.csdn.net/albertsh/article/details/97501893

MySQL中varchar和char區別(轉):https://www.cnblogs.com/webph/p/6679815.html

MySQL的char和varchar針對空格的處理:https://www.cnblogs.com/dsitn/p/7346761.html

相關文章