Mysql CHAR和VARCHAR类型
CHAR和VARCHAR类型相似,但在存储和检索方式上有所不同。它们在最大长度和是否保留尾部空格方面也有所区别。
CHAR和VARCHAR类型声明时需要指定一个长度,表示您想要存储的最大字符数。例如,CHAR(30)可以容纳最多30个字符。
CHAR列的长度在创建表时固定为您声明的长度。长度可以是0到255之间的任何值。当CHAR值被存储时,它们会被空格填充至指定长度。当CHAR值被检索时,除非启用了PAD_CHAR_TO_FULL_LENGTH SQL模式,否则会删除尾部空格。
VARCHAR列中的值是可变长度字符串。长度可以指定为0到65,535之间的值。VARCHAR的有效最大长度受到最大行大小(65,535字节,由所有列共享)和使用的字符集的限制。
与CHAR不同,VARCHAR值存储为1字节或2字节的长度前缀加上数据。长度前缀指示值中的字节数。如果值需要的字节数不超过255,则列使用一个长度字节;如果值可能需要超过255个字节,则使用两个长度字节。
如果没有启用严格的SQL模式,并且您将一个值赋给CHAR或VARCHAR列,该值超过了列的最大长度,则会截断该值以适应,并生成警告。对于非空格字符的截断,您可以通过使用严格的SQL模式来引发错误(而不是警告),并禁止插入值。
对于VARCHAR列,超过列长度的尾部空格在插入前会被截断,并生成警告,无论使用的SQL模式如何。对于CHAR列,无论SQL模式如何,插入值的多余尾部空格都会被静默地截断。
VARCHAR值在存储时不会被填充。在存储和检索值时,尾部空格会被保留,符合标准SQL。
下表通过显示将各种字符串值存储到CHAR(4)和VARCHAR(4)列中的结果来说明CHAR和VARCHAR之间的区别(假设列使用单字节字符集,如latin1)。
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 |
表格最后一行显示的值只有在不使用严格SQL模式时才适用;如果启用了严格模式,超过列长度的值将不会被存储,并且会导致错误。
InnoDB将长度大于或等于768字节的固定长度字段编码为可变长度字段,这些字段可以存储在页外。例如,如果字符集的最大字节长度大于3,如utf8mb4,那么CHAR(255)列可以超过768字节。
如果给定值被存储到CHAR(4)和VARCHAR(4)列中,从这些列检索的值并不总是相同的,因为在检索时会从CHAR列中移除尾部空格。以下示例说明了这种差异:
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)
在CHAR、VARCHAR和TEXT列中的值根据分配给该列的字符集排序规则进行排序和比较。
除了基于UCA 9.0.0及以上版本的Unicode排序规则具有NO PAD填充属性外,MySQL排序规则具有PAD SPACE填充属性。
要确定排序规则的填充属性,可以使用INFORMATION_SCHEMA COLLATIONS表,该表有PAD_ATTRIBUTE列。
对于非二进制字符串(CHAR、VARCHAR和TEXT值),字符串排序规则填充属性决定了字符串末尾尾随空格在比较中的处理方式。NO PAD排序规则将尾随空格视为比较中的重要字符,就像任何其他字符一样。PAD SPACE排序规则在比较中认为尾随空格不重要;字符串在不考虑尾随空格的情况下进行比较。服务器SQL模式对尾随空格的比较行为没有影响。
对于那些尾随填充字符被剥离或比较忽略它们的情况,如果一个列有一个需要唯一值的索引,插入到该列的值仅在尾随填充字符的数量上有差异,会导致重复键错误。例如,如果表中包含’a’,尝试存储’a ’会导致重复键错误。