MySQL中char與varchar都是字符類型,但是其在存儲,檢索方式,最大允許長度,尾部空字符處理方面都有所不同。

char與varchar在聲明時都可以指明一個長度值表示允許存儲的最大字符數(shù),例如:char(10) varchar(255)。
strict SQL模式在沒被激活的情況下,Mysql允許存儲大于char(varchar)聲明的最大長度的字符,mysql會把字符自動裁剪到符合長度要求,并且給出警告,如果strict SQL模式被激活,對于非空字符的截?cái)鄬?dǎo)致錯誤發(fā)生。
char是固定字符類型,在聲明的時候其大小就被確定,char允許聲明的長度為【0,255】。如果實(shí)際存儲的內(nèi)容小于指定的長度,char類型的聲明會導(dǎo)致值被以空格右填充到符合聲明的長度后再存儲,而在檢索的時候,如果 *PAD_CHAR_TO_FULL_LENGTH*SQL模式?jīng)]有被激活,內(nèi)容右邊的空格會被自動移除。
varchar是可變字符類型,其大小隨實(shí)際的存儲內(nèi)容而變化,varchar允許聲明的長度為【0,65535】。但實(shí)際上varchar有效的長度聲明受限于行大小65535bytes的限制,同時和所用的字符集也是有關(guān)系的。varchar存儲數(shù)據(jù)的時候需要1byte或2byte附加于實(shí)際數(shù)據(jù)之前指示實(shí)際存儲的數(shù)據(jù)長度。如果存儲的數(shù)據(jù)不大于255bytes則用1byte,反之則用2bytes。varchar不會自動對存入其的數(shù)據(jù)進(jìn)行空格填充,尾部空格在數(shù)據(jù)檢索時也會被保留下來。
| Value | CHAR(4) | Storage Required | VARCHAR(4) | Storage Required |
|---|---|---|---|---|
| ” | ’ ‘(4 spaces) | 4 bytes | ” | 1 byte |
| ‘a(chǎn)b’ | ‘a(chǎn)b ‘ | 4 bytes | ‘a(chǎn)b’ | 3 bytes |
| ‘a(chǎn)bcd’ | ‘a(chǎn)bcd’ | 4 bytes | ‘a(chǎn)bcd’ | 5 bytes |
| ‘a(chǎn)bcdefgh’ | ‘a(chǎn)bcd’ | 4 bytes | ‘a(chǎn)bcd’ | 5 bytes |
由于尾空格在char類型中檢索數(shù)據(jù)時會被自動移除的原因,給定的值,存儲于char,varchar后再分別提取可能會發(fā)現(xiàn)其內(nèi)容不一致。
mysql> CREATE TABLE vc (v VARCHAR(4), c CHAR(4));Query OK, 0 rows affected (0.01 sec)mysql> INSERT INTO vc VALUES ('ab ', 'ab ');Query OK, 1 row affected (0.00 sec)mysql> SELECT CONCAT('(', v, ')'), CONCAT('(', c, ')') FROM vc;+---------------------+---------------------+| CONCAT('(', v, ')') | CONCAT('(', c, ')') |+---------------------+---------------------+| (ab ) | (ab) |+---------------------+---------------------+1 row in set (0.06 sec)MySQL中所有的校對規(guī)則都是PADSPACE類型的,所以在比較時候的時候尾部空字符是不影響比較(不包括LIKE)結(jié)果的。該規(guī)則對所有MySQL版本都適用,也和SQL模式?jīng)]關(guān)系。
mysql> CREATE TABLE names (myname CHAR(10));Query OK, 0 rows affected (0.03 sec)mysql> INSERT INTO names VALUES ('Monty');Query OK, 1 row affected (0.00 sec)mysql> SELECT myname = 'Monty', myname = 'Monty ' FROM names;+------------------+--------------------+|myname = 'Monty' | myname = 'Monty ' |+------------------+--------------------+| 1 | 1 |+------------------+--------------------+1 row in set (0.00 sec)mysql> SELECT myname LIKE 'Monty', myname LIKE 'Monty ' FROM names;+---------------------+-----------------------+| myname LIKE 'Monty' | myname LIKE 'Monty ' |+---------------------+-----------------------+| 1 | 0 |+---------------------+-----------------------+1 row in set (0.00 sec)鑒于上述原因,在尾部的空字符會被自動剝離截?cái)嘁约氨容^時忽略尾部空字符的情況下,對于有unique約束的列,同時插入’a’, ‘a(chǎn) ‘將會導(dǎo)致duplicate-key的錯誤。
新聞熱點(diǎn)
疑難解答