官方文档地址:11.3.2 The CHAR and VARCHAR Types
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
字节,在一行中的所有列之间共享)和所使用的字符集。参见 8.4.7 对表列数和行大小的限制。
与CHAR
不同,VARCHAR
值在存储的时候会在数据前面加上1
字节或2
字节长度的前缀,长度前缀表示值中的字节数。如果值需要不超过255
个字节,则使用一个长度字节,如果值需要超过255
个字节,则使用两个长度字节。
如果没有启用严格 SQL 模式,并且将超过列最大长度的值分配给CHAR
或VARCHAR
列,该值会被截断以适合列的最大长度,并生成警告。要禁止非空格字符的截断,可以使用严格的 SQL 模式导致出现错误(而不是警告)并禁止插入值。参见 5.1.11 服务器 SQL 模式。
对于VARCHAR
列,超过列长度的尾随空格在插入之前被截断,并生成警告,无论使用的是哪种 SQL 模式。对于CHAR
列,无论使用哪种 SQL 模式,都静默地截断插入值的多余尾随空格。
VARCHAR
值在存储时不会被填充。在存储和检索值时保留尾随空格,这符合标准 SQL。
下表通过显示将各种字符串值存储到CHAR(4)
和VARCHAR(4)
列(假设该列使用一个单字节字符集,如latin1
)的结果,说明了CHAR
和VARCHAR
之间的区别。
仅当没有使用严格的 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
列中的值进行排序和比较。
MySQL 排序规则的 pad 属性是PAD SPACE
,而基于UCA 9.0.0
及更高版本的 Unicode 排序规则的 pad 属性是NO PAD
。(参见 10.10.1 Unicode 字符集)。
要确定排序规则的 pad 属性,请使用INFORMATION_SCHEMA
下的COLLATIONS
表,该表有一个PAD_ATTRIBUTE
列。
对于非二进制字符串(CHAR
、VARCHAR
和TEXT
值),字符串排序规则的 pad 属性决定比较字符串末尾的空格时的处理方法。NO PAD
排序法像对待任何其他字符一样对待末尾的空格。PAD SPACE
排序法在比较时将尾随空格视为不重要的,字符串的比较不考虑末尾的空格。对于尾随空格,服务器 SQL 模式对比较行为没有影响。
注意
关于 MySQL 字符集和排序的更多信息,参见 第10章 字符集,排序规则,Unicode。有关存储需求的其他信息,参见 11.7 数据类型存储要求。
对于那些删除了尾随字符或比较忽略它们的情况,如果列具有唯一值的索引,则向列中插入仅在尾随字符数量上不同的值将导致重复键错误。例如,如果一个表包含'a'
,尝试存储'a '
会导致重复键错误。