1500字范文,内容丰富有趣,写作好帮手!
1500字范文 > Mysql中char和varchar的区别

Mysql中char和varchar的区别

时间:2022-09-07 19:56:32

相关推荐

Mysql中char和varchar的区别

文章目录

前言问题起因length 和 char_length测试环境测试过程char和varchar区别总结

前言

这个标题起的过于俗套,前一段时间我还写了一篇总结《Mysql5.7版本中数据表字段可用的类型》来批判这种对比,原因是对比时没有指明数据库,内容写的是charvarcharnvarchar的对比,结果我测试了半天发现Mysql当前版本根本没有nvarchar,浪费来了不少时间。

问题起因

真香定律来的总是这么快,这才过了几天,我也来写写Mysql中charvarchar究竟有什么区别,起因是看到CSDN好友“铁柱同学”一篇关于innodb主键长度最大为767字节的讲解,里面涉及到一个char类型最大存储255个字符,按照utf8编码来看最大的字节数应该是255*3=765个字节的知识点。现在来看767的来源好像并不是256*3-1,而是255*3+2,这个2就是存储char类型字段中实际有多少个字节的。

有点跑题了,实际上是在研究索引长度的过程中,我发现我对charvarchar这两个类型一直存在着误解,因为一直做游戏开发的缘故,游戏数据的存储一般使用varbinary来存,导致我把字符和字节有点弄混了,所以我一直认为在utf8编码下char(9)可以存储9个英文字符,或者3个中文汉字,实际我做完实验后发现char(9)也可以正常存储9个汉字。

提到字符和字节,初学者可能会有点蒙,实际上它们两者之间是需要通过编码来转换的,之前做过游戏的多语言版本,所以对这一块还是比较熟的,字节就是计算机中的8个二进制位,而字符是每个语言中的不可分割的单元,字符转换成字节需要依赖编码,实际上编码就是一本大字典,里面对应了每个字符在当前编码下转换成字节是什么样的,ANSI是一本字典,UTF8也是一本字典,编码的类型还有很多,每种编码都记录了各自的转换结果。

举个例子,“中”这个字是汉字中的一个字符,在ANSI这本字典中对应的是2个字节,而在UTF8这本字典中对应的是3个字节,而C这个字母是英文中的一个字符,在ANSI这本字典中对应的是1个字节,而在UTF8这本字典中对应的同样是1个字节,从这个例子中可以简单理解下字节与字符的关系。

多说一句,不要认为UTF8编码中汉字转换成字节都是3个字节,实际情况是常用字一般都占用了3个字节,但是中国语言博大精深,光语言平面就单独占了好几个,有些汉字转换成UTF8编码可能需要4个字节,5个字节甚至是6个字节,这一点不要形成思维定式,认为汉字在UTF8编码下都是3个字节。

length 和 char_length

今天之前我是不知道Mysql还有一个char_length函数的,发现这个函数后越发感觉Mysql的强大,这两个函数的区别就是length用来统计字段中的字节数,char_length用来统计字段中的字符数,接下来我们用一个例子来看看这两个函数以及charvarchar的区别。

测试环境

Windows 10

Welcome to the MySQL monitor. Commands end with ; or \g.

Your MySQL connection id is 10

Server version: 5.7.21-log MySQL Community Server (GPL)

Copyright © 2000, , Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its affiliates. Other names may be trademarks of their respective owners.

Type ‘help;’ or ‘\h’ for help. Type ‘\c’ to clear the current input statement.

测试过程

首先创建一个带有charvarchar类型的测试表,查看表结构发现编码为utf8

mysql> create table diff(id int, s1 char(10), s2 varchar(10));Query OK, 0 rows affected (0.07 sec)mysql> show create table diff;+-------+------------------------------------------------------------------------+| Table | Create Table |+-------+------------------------------------------------------------------------+| diff | CREATE TABLE `diff` (`id` int(11) DEFAULT NULL,`s1` char(10) DEFAULT NULL,`s2` varchar(10) DEFAULT NULL) ENGINE=InnoDB DEFAULT CHARSET=utf8 |+-------+------------------------------------------------------------------------+1 row in set (0.07 sec)

插入少于10个字符的测试数据,然后查看结果,发现字节数为10,字符数为6

mysql> insert into diff values(1, "测试test", "测试test");Query OK, 1 row affected (0.01 sec)mysql> select id, s1, length(s1), char_length(s1), s2, length(s2), char_length(s2) from diff;+----+----------+------------+-----------------+----------+------------+-----------------+| id | s1 | length(s1) | char_length(s1) | s2 | length(s2) | char_length(s2) |+----+----------+------------+-----------------+----------+------------+-----------------+| 1 | 测试test | 10 |6 | 测试test | 10 |6 |+----+----------+------------+-----------------+----------+------------+-----------------+1 row in set (0.06 sec)

增加插入长度后发现,可以超过10个字节,可以完整存储10个汉字

mysql> insert into diff values(2, "测试策划和开发做游戏", "测试策划和开发做游戏");Query OK, 1 row affected (0.01 sec)mysql> select id, s1, length(s1), char_length(s1), s2, length(s2), char_length(s2) from diff;+----+----------------------+------------+-----------------+----------------------+------------+-----------------+| id | s1 | length(s1) | char_length(s1) | s2 | length(s2) | char_length(s2) |+----+----------------------+------------+-----------------+----------------------+------------+-----------------+| 1 | 测试test | 10 |6 | 测试test | 10 |6 || 2 | 测试策划和开发做游戏 | 30 | 10 | 测试策划和开发做游戏| 30 | 10 |+----+----------------------+------------+-----------------+----------------------+------------+-----------------+2 rows in set (0.10 sec)

分别增加s1和s2字段长度后发现,均无法正常插入,Mysql给出报错信息

mysql> insert into diff values(2, "测试策划和开发做游戏OK", "测试策划和开发做游戏");1406 - Data too long for column 's1' at row 1mysql> insert into diff values(2, "测试策划和开发做游戏", "测试策划和开发做游戏OK");1406 - Data too long for column 's2' at row 1mysql>

至此没有看出区别,在插入内容前后都加上空格测试一下

mysql> select id, s1, concat('#', s1, '$'), length(s1) as len_s1, char_length(s1) as clen_s1,s2, concat('#', s2, '$'), length(s2) as len_s2, char_length(s2) as clen_s2 from diff;+----+----------------------+------------------------+--------+---------+----------------------+------------------------+--------+---------+| id | s1 | concat('#', s1, '$') | len_s1 | clen_s1 | s2 | concat('#', s2, '$') | len_s2 | clen_s2 |+----+----------------------+------------------------+--------+---------+----------------------+------------------------+--------+---------+| 1 | 测试test | #测试test$ |10 | 6 | 测试test | #测试test$ |10 | 6 || 2 | 测试策划和开发做游戏| #测试策划和开发做游戏$ |30 |10 | 测试策划和开发做游戏 | #测试策划和开发做游戏$|30 |10 || 3 | OK | # OK$ |3 | 3 | OK | # OK $ |4 | 4 |+----+----------------------+------------------------+--------+---------+----------------------+------------------------+--------+---------+

这一次出现了区别,char类型的字段去掉了尾部的空格,而varcahr了类型的字段原样存储,没有去掉尾部空格,两者对于头部的空格都是存储的,这导致两者显示的字节数和字符数都不相同了。

分别使用不带空格、带头部空格,头尾都带空格进行测试

mysql> select * from diff where s1 = 'OK ';Empty setmysql> select * from diff where s2 = 'OK ';Empty setmysql> select * from diff where s1 = ' OK ';+----+-----+------+| id | s1 | s2 |+----+-----+------+| 3 | OK | OK |+----+-----+------+1 row in set (0.05 sec)mysql> select * from diff where s2 = ' OK ';+----+-----+------+| id | s1 | s2 |+----+-----+------+| 3 | OK | OK |+----+-----+------+1 row in set (0.05 sec)mysql> select * from diff where s1 = ' OK';+----+-----+------+| id | s1 | s2 |+----+-----+------+| 3 | OK | OK |+----+-----+------+1 row in set (0.05 sec)mysql> select * from diff where s2 = ' OK';+----+-----+------+| id | s1 | s2 |+----+-----+------+| 3 | OK | OK |+----+-----+------+1 row in set (0.04 sec)

测试结果可能让人出乎意料,虽然s1和s2中存储的内容不同(差一个空格),但是查找时的行为却完全一样,这说明查找时尾部的空格并不会被考虑。

char和varchar区别

做了半天试验发现char和varchar还是没有多大区别,实际上有些区别通过表面数据是测试不出来的,具体区别整理如下:

总结

char(n)中的n是字符数,范围是0~255(额外需要1到2个字节来存长度)varchar(n)中的n也是字符数,但是最大值需要通过编码来算,不能超过65535字节(从中还需要拿出1到2个字节来存长度)一般定长的数据选用char类型,比如身份证号,手机号,电话等,长度变化很大的可以使用varchar类型注意尾部空格的匹配,特别是插入时和使用like查找时

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。