MySQL 8.0 参考手册  / 第 11 章数据类型  / 11.3 字符串数据类型  /  11.3.2 CHAR 和 VARCHAR 类型

11.3.2 CHAR 和 VARCHAR 类型

和类型相似,但存储和检索方式不同CHARVARCHAR它们在最大长度和是否保留尾随空格方面也不同。

CHAR和类型声明了一个长度, 该VARCHAR长度指示您要存储的最大字符数。例如, CHAR(30)最多可容纳 30 个字符。

列的长度CHAR固定为您在创建表时声明的长度。长度可以是 0 到 255 之间的任何值。CHAR 在存储值时,它们会用空格向右填充到指定的长度。检索值时CHAR,将删除尾随空格,除非 PAD_CHAR_TO_FULL_LENGTH启用 SQL 模式。

列中的值VARCHAR是可变长度的字符串。长度可以指定为 0 到 65,535 之间的值。a 的有效最大长度 VARCHAR取决于最大行大小(65,535 字节,由所有列共享)和使用的字符集。请参阅第 8.4.7 节,“表列数和行大小的限制”

与 相比CHARVARCHAR值存储为 1 字节或 2 字节长度前缀加上数据。长度前缀指示值中的字节数。如果值需要不超过 255 个字节,一列使用一个长度字节,如果值可能需要超过 255 个字节,则使用两个长度字节。

如果未启用严格的 SQL 模式,并且您为 CHARVARCHAR列分配了一个超过该列最大长度的值,该值将被截断以适合并生成警告。对于非空格字符的截断,您可能会导致发生错误(而不是警告)并通过使用严格的 SQL 模式禁止插入值。请参阅第 5.1.10 节,“服务器 SQL 模式”

对于VARCHAR列,超出列长度的尾随空格在插入之前被截断并生成警告,而不管使用的 SQL 模式如何。对于 CHAR列,无论 SQL 模式如何,都会以静默方式截断插入值中多余的尾随空格。

VARCHAR值在存储时不会被填充。根据标准 SQL,在存储和检索值时保留尾随空格。

下表 通过显示将各种字符串值存储到 CHAR和 列(假设该列使用单字节字符集,例如)的结果来说明和之间的差异。 VARCHARCHAR(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)如果字符集的最大字节长度大于 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 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)

CHARVARCHAR和列中的 值TEXT根据分配给该列的字符集排序规则进行排序和比较。

所有 MySQL 排序规则都是类型PAD SPACE。这意味着所有CHARVARCHARTEXT值的比较都不会考虑任何尾随空格。 比较在这种情况下不包括 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)

这不受服务器 SQL 模式的影响。

笔记

有关 MySQL 字符集和排序规则的更多信息,请参阅第 10 章,字符集、排序规则、Unicode。有关存储要求的其他信息,请参阅 第 11.6 节,“数据类型存储要求”

对于尾随填充字符被删除或比较忽略它们的情况,如果列具有需要唯一值的索引,则将仅尾随填充字符数量不同的列值插入到列中会导致重复键错误。例如,如果表包含'a',则尝试存储'a '会导致重复键错误。