CHAR 和 VARCHAR 类型
该CHAR
和VARCHAR
类型相似,但它们被存储和检索的方式不同。它们的最大长度以及是否保留尾随空格也不同。
该CHAR
和VARCHAR
类型的声明,其长度指示要存储的最大字符数。例如,CHAR(30)
最多可容纳30个字符。
一个长度CHAR
列被固定在创建表声明的长度。长度可以是0到255之间的任何值。CHAR
存储值时,它们会用空格右填充到指定的长度。当CHAR
被检索到的值,拖尾的空格被删除,除非PAD_CHAR_TO_FULL_LENGTH
启用SQL模式。
VARCHAR
列中的值是可变长度的字符串。长度可以指定为0到65535之间的值。a的有效最大长度VARCHAR
取决于最大行大小(65,535字节,在所有列之间共享)和所使用的字符集。请参见“数据表的限制”。
与相比CHAR
,VARCHAR
值存储为1字节或2字节长的前缀加数据。长度前缀指示值中的字节数。如果值要求不超过255个字节,则一列使用一个长度字节;如果值可能需要不超过255个字节,则一列使用两个长度字节。
如果未启用严格的SQL模式,并且您为CHAR
或VARCHAR
列分配的值超过了列的最大长度,则该值将被截断以适合并生成警告。对于非空格字符的截断,可以使用严格的SQL模式导致发生错误(而不是警告)并抑制该值的插入。请参见“服务器SQL模式”。
对于VARCHAR
列,无论使用哪种SQL模式,插入前都会截断超出列长度的尾随空格,并生成警告。对于CHAR
列,无论SQL模式如何,都将以静默方式从插入值中截断多余的尾随空格。
VARCHAR
值在存储时不会填充。根据标准SQL,在存储和检索值时保留尾随空格。
下表说明了之间的区别,CHAR
并VARCHAR
显示了将各种字符串值存储到CHAR(4)
和VARCHAR(4)
列中的结果(假设该列使用诸如的单字节字符集latin1
)。
值 | CHAR(4) | 需要存储 | VARCHAR(4) | 需要存储 |
---|---|---|---|---|
'' | '' | 4字节 | '' | 1个字节 |
'ab' | 'ab ' | 4字节 | 'ab' | 3个字节 |
'abcd' | 'abcd' | 4字节 | 'abcd' | 5字节 |
'abcdefgh' | 'abcd' | 4字节 | 'abcd' | 5字节 |
显示在表最后一行中的值仅在不使用严格模式时适用;如果MySQL在严格模式下运行,则不会存储超过列长度的值,并会导致错误。
InnoDB
将长度大于或等于768字节的固定长度字段编码为可变长度字段,可以将其存储在页面外。例如,CHAR(255)
如果字符集的最大字节长度大于3,则该列可以超过768个字节(与相同)utf8mb4
。
如果将给定值存储在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 vcVALUES ('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)
in CHAR
和VARCHAR
column中的值将根据分配给该列的字符集校验规则进行校验和比较。
大多数MySQL归类均具有PAD SPACE的pad属性。例外是基于UCA 9.0.0和更高版本的Unicode归类,其填充属性为NO PAD。(请参见“ Unicode字符集”)。
要确定校验规则的pad属性,请使用INFORMATION_SCHEMA
COLLATIONS
具有一PAD_ATTRIBUTE
列的表。
垫属性确定尾部空格是如何用于非二进制字符串(比较处理CHAR
,VARCHAR
和TEXT
值)。没有PAD校验规则像对待其他字符一样对待字符串末尾的空格。对于PAD SPACE归类,尾随空格在比较中微不足道;比较字符串时不考虑任何尾随空格。在本文中,“比较”不包括LIKE
模式匹配运算符,其尾随空格很重要。例如:
mysql>CREATE TABLE names (myname CHAR(10)); Query OK, 0 rows affected (0.03 sec) mysql>INSERT INTO names VALUES ('Jones'); Query OK, 1 row affected (0.00 sec) mysql>SELECT myname = 'Jones', myname = 'Jones 'FROM names ; +-------------------- +-------------------- + | myname = 'Jones' | myname = 'Jones ' | +-------------------- +-------------------- + | 1 | 1 | +-------------------- +-------------------- + 1 row in set (0.00 sec) mysql>SELECT myname LIKE 'Jones', myname LIKE 'Jones 'FROM names ; +----------------------- +----------------------- + | myname LIKE 'Jones' | myname LIKE 'Jones ' | +----------------------- +----------------------- + | 1 | 0 | +----------------------- +----------------------- + 1 row in set (0.00 sec)
对于所有MySQL版本都是如此,并且不受服务器SQL模式的影响。
注意有关MySQL字符集和校验规则的更多信息,请参见字符集,校验规则,Unicode。有关存储要求的其他信息,请参见“数据类型存储要求”。
对于剥离尾随字符或比较忽略它们的情况,如果一列具有要求唯一值的索引,则将仅尾随字符数不同的值插入列中将导致重复键错误。例如,如果表包含'a'
,则尝试存储'a '
会导致重复键错误。