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 字节,列使用一个长度字节;否则,使用两个长度字节。
如果未启用严格 SQL 模式,并且您将值分配给 CHAR 或 VARCHAR 列,超过列的最大长度,值将被截断以适应,并生成警告。对于非空格字符的截断,您可以使用严格 SQL 模式来生成错误(而不是警告)并抑制值的插入。见 第 7.1.11 节,“服务器 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 字节 |
表格最后一行所示的值仅在 不使用严格 SQL 模式 时适用;如果启用严格模式,超过列长度的值将 不存储,并出现错误。
InnoDB
将长度大于或等于 768 字节的固定长度字段编码为可变长度字段,可以存储在页面外。例如,CHAR(255)
列可以超过 768 字节,如果字符集的最大字节长度大于 3,如 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 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
。(见 第 12.10.1 节,“Unicode 字符集”)。
要确定排序的 pad 属性,可以使用 INFORMATION_SCHEMA
COLLATIONS
表,该表具有 PAD_ATTRIBUTE
列。
对于非二进制字符串(CHAR
、VARCHAR
和 TEXT
值),字符串排序pad 属性确定比较字符串末尾的空格处理方式。NO PAD
排序将末尾空格视为重要的比较字符。PAD SPACE
排序将末尾空格视为无关紧要的比较字符;字符串比较时忽略末尾空格。请参阅 比较中的末尾空格处理。服务器 SQL 模式对比较行为没有影响,关于末尾空格的处理。
有关 MySQL 字符集和排序的更多信息,请参阅 第 12 章,《字符集、排序、Unicode》。有关存储要求的更多信息,请参阅 第 13.7 节,“数据类型存储要求”。
在那些末尾填充字符被剥离或比较忽略它们的情况下,如果列具有唯一值索引,插入到该列的值仅在末尾填充字符数量上不同,将导致重复键错误。例如,如果表中包含 'a'
,尝试存储 'a '
将导致重复键错误。