13.3.2 CHAR 和 VARCHAR 类型
CHAR 和 VARCHAR 类型类似,但在存储和检索方式、最大长度和尾部空格保留方面有所不同。
CHAR 和 VARCHAR 类型在创建表时指定的长度表示要存储的最大字符数。例如,CHAR(30)
可以存储最多 30 个字符。
CHAR 列的长度固定为创建表时指定的长度,可以是任何值从 0 到 255。当存储 CHAR 值时,它们将被右对齐到指定长度。检索 CHAR 值时,除非启用 PAD_CHAR_TO_FULL_LENGTH
SQL 模式,否则尾部空格将被删除。
VARCHAR 列中的值是可变长度字符串。长度可以指定为 0 到 65,535。VARCHAR 的实际最大长度受表行大小(共享所有列)和字符集的限制。见第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
)。
Value | CHAR(4) |
Storage Required | VARCHAR(4) |
Storage Required |
---|---|---|---|---|
'' |
' ' |
4 bytes | '' |
1 byte |
'ab' |
'ab ' |
4 bytes | 'ab' |
3 bytes |
'abcd' |
'abcd' |
4 bytes | 'abcd' |
5 bytes |
'abcdefgh' |
'abcd' |
4 bytes | 'abcd' |
5 bytes |
最后一行表格中显示的值仅在不使用严格SQL模式下有效;如果启用严格模式,超过列长度的值不会被存储,并且会出现错误。
InnoDB 将固定长度字段长度大于或等于768字节的字段编码为可变长度字段,可以在页面外存储。例如,一个CHAR(255)
列如果字符集的最大字节数量大于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 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 字符集和排序集的更多信息,见Chapter 12, 字符集、排序集、Unicode
。关于存储要求的更多信息,见第13.7节,“数据类型存储要求”。
对于那些去除尾部填充字符或忽略它们的比较,如果一个列需要唯一值的索引,插入只在尾部填充字符数量不同但实际值相同的值将导致重复键错误。例如,如果一张表包含 'a'
,尝试存储 'a '
将导致重复键错误。