字符與字節的區別
一個字符由於所使用的字符集的不同,會並存儲在一個或多個字節中,所以一個字符占用多少個字節取決於所使用的字符集
注意:char與varchar后面接的數據大小為存儲的字符數,而不是字節數
char與varchar的差異
為方便說明,我們下面定義一個表:
CREATE TABLE `t_users` (
`name` CHAR(10) NOT NULL,
`subject` VARCHAR(10) NOT NULL,
`description` CHAR(10) NOT NULL
)
INSERT INTO `t_users` (`name`, `subject`, `description`) VALUES ('zejin', 'zejin ', 'zejin ');
存數據時的區別
char定義的是固定長度,長度范圍為0-255,存儲時,如果字符數沒有達到定義的位數,會在后面用空格補全存入數據庫中,在上例中,name實際存儲在數據中的數據為'zejin '
varchar是變長長度,長度范圍為0-65535,存儲時,如果字符沒有達到定義的位數,也不會在后面補空格,在上例subject字段中,實際存儲在數據中的數據為'zejin ',當然還有一或兩個字節來描述該
字節長度
取數據時的區別
數據庫取char的數據時,會把后面的空格全部丟棄掉,譬如上例中的description字段取出來時只剩zejin
mysql> select concat('(',name,')'),concat('(',description,')') from t_users;
+----------------------+-----------------------------+
| concat('(',name,')') | concat('(',description,')') |
+----------------------+-----------------------------+
| (zejin) | (zejin) |
+----------------------+-----------------------------+
1 row in set (0.00 sec)
也就是說,在char中的尾部存入空格時,最后取出來都會被丟棄
當然指定
PAD_CHAR_TO_FULL_LENGTH
時,在取數據時讓尾部的空格保留
而數據庫在取varchar數據時,尾部空格會保留,譬如
subject字段:
mysql> select concat('(',subject,')'),concat('(',description,')') from t_users;
+-------------------------+-----------------------------+
| concat('(',subject,')') | concat('(',description,')') |
+-------------------------+-----------------------------+
| (zejin ) | (zejin) |
+-------------------------+-----------------------------+
1 row in set (0.00 sec)
占用字節差別
以latin編碼為便,一個字符占用一個字節。
Value | CHAR(4) | Storage Required | VARCHAR(4) | Storage Required |
'' | ' ' | 4 bytes | '' | 1 byte |
'ab' | 'ab ' | 4 bytes | 'ab' | 3 bytes |
'abcd' | 'abcd' | 4 bytes | 'abcd' | 5 bytes |
'abcdefgh' | 'abcd' | 4 bytes | 'abcd' | 5 bytes |
可以用上表來表示,當定義char時,不管你存入多少字符,都會占用到你定義的字符數,而用varchar時,則和你輸入的字符數有關,會多一到兩個字節來記錄字節長度,當數據位占用的字節數小於255時,用1個字節來記錄長度,數據位占用字節數大於255時,用2個字節來記錄長度,還有一位來記錄是否為nul值
注意
mysql每一行的最大字節數為65535,當你使用utf8,一個字符有可能占用三個字節的時候,varchar如果定義允許空的話能定義的最大長度為(65535-1-2)/3=21844.
Mysql在對比char,varchar,text類型的數據時,是不會把尾部的空格考慮在內的,這對所有字符集都適用,但在這里是除了like比較符的,譬如:
mysql> select name='zejin',name='zejin ' from t_users;
+--------------+----------------+
| name='zejin' | name='zejin ' |
+--------------+----------------+
| 1 | 1 |
+--------------+----------------+
1 row in set (0.00 sec)
mysql> select name like 'zejin',name like 'zejin ' from t_users;
+-------------------+---------------------+
| name like 'zejin' | name like 'zejin ' |
+-------------------+---------------------+
| 1 | 0 |
+-------------------+---------------------+
1 row in set (0.00 sec)