CHAR和VARCHAR类型
该CHAR
和VARCHAR
类型相似,但它们被存储和检索的方式不同。它们的最大长度以及是否保留尾随空格也不同。
该CHAR
和VARCHAR
类型的声明,其长度指示要存储的最大字符数。例如, CHAR(30)
最多可容纳30个字符。
一个长度CHAR
列被固定在创建表声明的长度。长度可以是0到255之间的任何值。CHAR
存储值时,将在它们的右边填充空格以达到指定的长度。当CHAR
被检索到的值,拖尾的空格被删除,除非 PAD_CHAR_TO_FULL_LENGTH
启用SQL模式。
VARCHAR
列中的 值是可变长度的字符串。长度可以指定为0到65535之间的值。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模式的影响。