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 字节,所有列共享)和使用的字符集。请参阅 第 10.4.7 节“表列数和行大小的限制”。
与 CHAR
相反,VARCHAR
值存储为 1 字节或 2 字节的长度前缀加上数据。长度前缀表示值中的字节数。如果值不超过 255 个字节,则列使用一个长度字节;如果值可能超过 255 个字节,则使用两个长度字节。
如果未启用严格 SQL 模式,并且为 CHAR
或 VARCHAR
列分配的值超过了列的最大长度,则该值将被截断以适应该长度,并生成警告。对于非空格字符的截断,您可以使用严格 SQL 模式导致发生错误(而不是警告)并禁止插入该值。请参阅 第 7.1.11 节“服务器 SQL 模式”。
对于 VARCHAR
列,无论使用何种 SQL 模式,在插入之前,超出列长度的尾随空格都会被截断,并生成警告。对于 CHAR
列,无论 SQL 模式如何,插入值中多余的尾随空格的截断都会静默执行。
存储 VARCHAR
值时不会填充它们。存储和检索值时,尾随空格会保留下来,这符合标准 SQL。
下表通过显示将各种字符串值存储到 CHAR(4)
和 VARCHAR(4)
列的结果(假设该列使用单字节字符集,例如 latin1
),说明了 CHAR
和 VARCHAR
之间的区别。
值 | CHAR(4) |
所需存储空间 | VARCHAR(4) |
所需存储空间 |
---|---|---|---|---|
'' |
' ' |
4 字节 | '' |
1 字节 |
'ab' |
'ab ' |
4 字节 | 'ab' |
3 字节 |
'abcd' |
'abcd' |
4 字节 | 'abcd' |
5 字节 |
'abcdefgh' |
'abcd' |
4 字节 | 'abcd' |
5 字节 |
表中最后一行显示的存储值仅在不使用严格 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 SPACE
,但基于 UCA 9.0.0 及更高版本的 Unicode 排序规则除外,它们的填充属性为 NO PAD
。(请参阅 第 12.10.1 节“Unicode 字符集”)。
要确定排序规则的填充属性,请使用 INFORMATION_SCHEMA
COLLATIONS
表,该表具有 PAD_ATTRIBUTE
列。
对于非二进制字符串(CHAR
、VARCHAR
和 TEXT
值),字符串排序规则的填充属性决定了在比较字符串末尾的尾随空格时的处理方式。NO PAD
排序规则在比较中将尾随空格视为有效字符,就像任何其他字符一样。PAD SPACE
排序规则在比较中将尾随空格视为无效字符;字符串的比较不考虑尾随空格。请参阅 比较中的尾随空格处理。服务器 SQL 模式对与尾随空格相关的比较行为没有影响。
有关 MySQL 字符集和排序规则的更多信息,请参阅 第 12 章“字符集、排序规则、Unicode”。有关存储需求的其他信息,请参阅 第 13.7 节“数据类型存储需求”。
对于删除尾随填充字符或比较忽略它们的情况,如果某个列的索引要求值唯一,则在该列中插入仅尾随填充字符数量不同的值会导致重复键错误。例如,如果一个表包含 'a'
,则尝试存储 'a '
会导致重复键错误。