和类型相似,但存储和检索方式不同CHAR
。VARCHAR
它们在最大长度和是否保留尾随空格方面也不同。
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 节,“表列数和行大小的限制”。
与 相比CHAR
,
VARCHAR
值存储为 1 字节或 2 字节长度前缀加上数据。长度前缀指示值中的字节数。如果值需要不超过 255 个字节,一列使用一个长度字节,如果值可能需要超过 255 个字节,则使用两个长度字节。
如果未启用严格的 SQL 模式,并且您为
CHAR
或VARCHAR
列分配了一个超过该列最大长度的值,该值将被截断以适合并生成警告。对于非空格字符的截断,您可能会导致发生错误(而不是警告)并通过使用严格的 SQL 模式禁止插入值。请参阅第 5.1.10 节,“服务器 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)
如果字符集的最大字节长度大于 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)
CHAR
、VARCHAR
和列中的
值TEXT
根据分配给该列的字符集排序规则进行排序和比较。
所有 MySQL 排序规则都是类型PAD SPACE
。这意味着所有CHAR
、
VARCHAR
和TEXT
值的比较都不会考虑任何尾随空格。
“比较”在这种情况下不包括
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 '
会导致重复键错误。