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 模式时适用;如果启用了严格模式,则不会存储超过列长度的值,并且会导致错误。
如果给定值的长度大于或等于 768 字节,则 InnoDB
会将其编码为变长字段,这些字段可以存储在页外。例如,如果字符集的最大字节长度大于 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 '
会导致重复键错误。