mysql char 和 varchar类型的异同

charvarchar类型很相似,但是在存储、最大字符长度、是否保留尾部空格等方面略有不同。

charvarchar都声明了一个你希望存储的字符串的最大长度,比如char(30)类型的字段最大多可以存储30个字符。

char类型的字段长度是固定的,长度为0-255之间,char类型字段存储时,如果长度不足你定义的长度,则mysql会默认使用空格填冲到字符串右边,以使字符串长度和你定义的长度一样。而当需要获取char类型字段的值时,系统又会自动将尾部空格都去掉后再返回。当然如果你不希望去掉尾部空格,你可以开启PAD_CHAR_TO_FULL_LENGTH 模式。

mysql> SET sql_mode = 'PAD_CHAR_TO_FULL_LENGTH';
Query OK, 0 rows affected (0.00 sec)

varchar类型字段是变长类型的字符串,长度为0-65535之间。varchar的最大有效长度受限于每行的最大空间(65535字节,所有列共享这个空间)和每个字符使用的空间大小。参考表的行大小和列数限制

(译注:这里一定要分清长度和大小的概念,比如字符串"123你好",它的长度为5,但是他所占字节数就要依赖于字符串编码了,如果是utf8,则中文字符就占用三个字节了,占用的字节数为12,所以varchar(65535)可能存的字符长度要远小于65535)

相较于charvarchar还会在数据前面加1-2字节的额外长度,用来记录数据的字节数。如果数据大小不超过255字节,则用一个字节存长度就好,否则需要两个字节。

如果没有开启strict模式,则当数据超过char或者varchar类型的最大长度时,数据就会被截掉并且触发一条告警。如果不希望数据隐式的被截断,你也可以通过打开strict模式,从而让系统抛出错误。参考SQL模式

对于varchar,超过长度的尾部空格会被截断后再插入并且生成一条告警,不管是是否使用strict模式。对于char,超过长度的尾部空格则在插入后被自动截断,不管是是否使用strict模式。

varchar列数据不会自动填充,尾部空格也会保存入库及被取出,保持和标准SQL一致。

下表展示了char(4)和varchar(4)两列在存储方面的一些差别。

数据char(4)存储大小varchar(4)存储大小
‘’‘ ’4字节‘’1字节
‘ab’‘ab ’4字节‘ab’3字节
‘abcd’‘abcd’4字节‘abcd’5字节
‘abcdefh’‘abcd ’4字节‘abcd’5字节

上面最后一行数据只有在非strict模式下才能插入成功,否则将会得到一条插入失败的报错信息。

InnoDB将长度大于或等于768字节的固定长度字段编码为可变长度字段,可以将其存储在页外。比如如果字符最大字节数超过3的话(utf8mb4编码最大为4字节),char(255)的存储大小可能就超过768字节了。

同一个字符串,存到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列的存储和比较都是基于列定义的字符集的校对规则的。

大多数MySQL的校对规则都有一个填充属性PAD SPACE。只有基于UCA9.0.0或者更高版本的Unicode字符集不一样,它的属性名是NO PAD

如果需要了解校对规则的属性,可以查看表 INFORMATION_SCHEMA.COLLATIONS。

当前非二进制字符串(char, varchar, text)进行比较时,填充属性决定了尾部空格的处理方式。NO PAD校对规则会将尾部空格进行比较,PAD SPACE校对规则则会忽略尾部空格进行比较。但是通过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)

这个在所有MySQL版本以及任何SQL模式下都是通用的。

对于这些尾部填充空格被删除或者比较时被忽略的情形,如果某列要求为唯一索引,当插入只有尾部空格不一样的数据时,就会报重复列的错误。比如表中已经有一列的内容为’a’, 当想要插入’a '时就报错了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值