CHAR与VARCHAR详解 char 与varchar
wptr33 2024-12-26 17:07 17 浏览
前言:
前面写过一篇介绍int类型的文章,一直想写一篇介绍字符串字段类型的文章,一直拖着也没思路要怎么下手。最近多关注了下这方面的文章,决定还是把拖了好久的文章了结了吧。本篇文章主要会介绍字符串类型char及varchar的用法及区别。
本文实验环境为MySQL 5.7.23版本,存储引擎为Innodb,sql_mode采用严格模式,字符集是utf8。
▍1.CHAR类型介绍
我们平时使用char类型定义字段时,往往会指定其长度M,即char(M)。其实M指的是字符数,即这个字段最多存储多少个字符,M可不指定,默认为1,范围是[0,255],单个字母、数字、中文等都是占用一个字符。utf8字符集下一个中文字符占用3个字节。下面我们简单测试下:
# 假设以如下建表语句创建测试表 CREATE TABLE `char_tb1` ( `col1` char DEFAULT NULL, `col2` char(5) DEFAULT NULL, `col3` char(10) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8; # 进入数据库查询建表语句如下 发现char(M) M可不指定,默认为1 mysql> show create table char_tb1\G *************************** 1. row *************************** Table: char_tb1 Create Table: CREATE TABLE `char_tb1` ( `col1` char(1) DEFAULT NULL, `col2` char(5) DEFAULT NULL, `col3` char(10) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8 1 row in set (0.00 sec) # 插入数据 可以看出M表示保存的最大字符数,字母、数字、中文等都是占用一个字符 mysql> insert into char_tb1 (col1) values ('a'),('1'),('王'),(']'); Query OK, 4 rows affected (0.01 sec) mysql> insert into char_tb1 (col1) values ('aa'),('12'); ERROR 1406 (22001): Data too long for column 'col1' at row 1 mysql> select * from char_tb1; +------+------+------+ | col1 | col2 | col3 | +------+------+------+ | a | NULL | NULL | | 1 | NULL | NULL | | 王 | NULL | NULL | | ] | NULL | NULL | +------+------+------+ 4 rows in set (0.00 sec) mysql> insert into char_tb1 (col2) values ('abcd'),('王-123'),('^*123'),('12'),('一二三四五'); Query OK, 5 rows affected (0.01 sec) mysql> insert into char_tb1 (col2) values ('abcdef'); ERROR 1406 (22001): Data too long for column 'col2' at row 1 mysql> select * from char_tb1; +------+-----------------+------+ | col1 | col2 | col3 | +------+-----------------+------+ | a | NULL | NULL | | 1 | NULL | NULL | | 王 | NULL | NULL | | ] | NULL | NULL | | NULL | abcd | NULL | | NULL | 王-123 | NULL | | NULL | ^*123 | NULL | | NULL | 12 | NULL | | NULL | 一二三四五 | NULL | +------+-----------------+------+ 9 rows in set (0.00 sec) # 下面测试发现M的范围是[0,255] mysql> alter table char_tb1 add column col4 char(0); Query OK, 0 rows affected (0.10 sec) Records: 0 Duplicates: 0 Warnings: 0 mysql> alter table char_tb1 add column col5 char(255); Query OK, 0 rows affected (0.11 sec) Records: 0 Duplicates: 0 Warnings: 0 mysql> alter table char_tb1 add column col5 char(256); ERROR 1074 (42000): Column length too big for column 'col5' (max = 255); use BLOB or TEXT instead
▍2.VARCHAR类型介绍
同样的,varchar(M)中的的M表示保存的最大字符数,单个字母、数字、中文等都是占用一个字符。varchar可存储的长度范围为0-65535字节,此外,varchar需要使用1或者2个额外字节记录字符串的长度:如果列的最大长度小于或等于255字节,则只使用1个字节表示,否则使用2个字节。对于Innodb引擎,utf8字符集来说,单个中文字符占用3个字节,所以varchar(M)中的M最大不会超过21845,即M的范围是[0,21845),并且M必须指定。另外MySQL规定:单个字段长度不大于65535字节;单行最大限制为65535,这里不包括TEXT、BLOB字段。即单张表中的所有varchar字段定义的长度之和不能大于65535,所以并不是所有varchar(M)字段中的M都可以取到21844,下面我们来验证下:
# 假设以如下建表语句创建测试表 CREATE TABLE `varchar_tb1` ( `col1` varchar(0) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8; # 查看建表语句 增加字段 发现M必须指定 mysql> show create table varchar_tb1\G *************************** 1. row *************************** Table: varchar_tb1 Create Table: CREATE TABLE `varchar_tb1` ( `col1` varchar(0) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8 1 row in set (0.00 sec) mysql> alter table varchar_tb1 add column col2 varchar; ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '' at line 1 # 下面测试证明M最大可取到21844 mysql> CREATE TABLE `varchar_tb2` (col1 varchar(21844)); Query OK, 0 rows affected (0.04 sec) mysql> CREATE TABLE `varchar_tb3` (col1 varchar(218445)); ERROR 1074 (42000): Column length too big for column 'col1' (max = 21845); use BLOB or TEXT instead # 下面测试证明单行最大限制为65535字节 mysql> CREATE TABLE `varchar_tb3` (col1 varchar(10)); Query OK, 0 rows affected (0.04 sec) mysql> alter table varchar_tb3 add column col2 varchar(21844); ERROR 1118 (42000): Row size too large. The maximum row size for the used table type, not counting BLOBs, is 65535. This includes storage overhead, check the manual. You have to change some columns to TEXT or BLOBs mysql> alter table varchar_tb3 add column col2 varchar(21834); ERROR 1118 (42000): Row size too large. The maximum row size for the used table type, not counting BLOBs, is 65535. This includes storage overhead, check the manual. You have to change some columns to TEXT or BLOBs mysql> alter table varchar_tb3 add column col2 varchar(21833); Query OK, 0 rows affected (0.09 sec) Records: 0 Duplicates: 0 Warnings: 0 mysql> show create table varchar_tb3\G *************************** 1. row *************************** Table: varchar_tb3 Create Table: CREATE TABLE `varchar_tb3` ( `col1` varchar(10) DEFAULT NULL, `col2` varchar(21833) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8 1 row in set (0.00 sec)
▍3.CHAR与VARCHAR比较
CHAR类型是定长的,MySQL总是根据定义的字符串长度分配足够的空间。当保存CHAR值时,在它们的右边填充空格以达到指定的长度,当检索到CHAR值时,尾部的空格被删除掉。
VARCHAR类型用于存储可变长字符串,存储时,如果字符没有达到定义的位数,也不会在后面补空格。但是,由于行是变长的,在UPDATE时可能使行变得比原来更长,这就导致需要做额外的工作。如果一个行占用的空间增长,并且在页内没有更多的空间可以存储,在这种情况下InnoDB需要分裂页来使行可以放进页内,这样会增加碎片。
下面简单总结下CHAR与VARCHAR字段类型的适用场景:
CHAR适合存储很短的字符串,或者所有值都接近同一个长度。例如,CHAR非常适合存储密码的MD5值,因为这是一个定长的值。对于经常变更的数据,CHAR也比VARCHAR更好,因为定长的CHAR类型不容易产生碎片。对于非常短的列,CHAR比VARCHAR在存储空间上也更有效率。例如用CHAR(1)来存储只有Y和N的值,如果采用单字节字符集只需要一个字节,但是VARCHAR(1)却需要两个字节,因为还有一个记录长度的额外字节。
下面这些情况下使用VARCHAR是合适的:字符串很长或者所要存储的字符串长短不一,差别很大;字符串列的最大长度比平均长度大得多;列的更新很少,所以碎片不是问题。
额外说明下,我们在定义字段最大长度时应该按需分配,提前做好预估。特别是对于VARCHAR字段,有人认为反正VARCHAR数据类型是根据实际的需要来分配长度的,还不如给大一点呢。但事实不是这样的,比如现在需要存储一个地址信息,根据评估,只要使用100个字符就可以了,我们可以使用VARCHAR(100)或VARCHAR(200)来存储,虽然它们用来存储90个字符的数据,其存储空间相同,但是对于内存的消耗是不同的。更长的列会消耗更多的内存,因为MySQL通常会分配固定大小的内存块来保存内部值,尤其是使用内存临时表进行排列或者操作时会特别糟糕。所以我们在分配VARCHAR数据类型时仍然不能够太过于慷慨。还是要评估实际需要的长度,然后选择一个最长的字段来设置字符长度。如果为了考虑冗余,可以留10%左右的字符长度。千万不能认为VARCHAR是根据实际长度来分配存储空间,而随意的分配长度,或者说干脆使用最大的字符长度。
总结:
本文分别介绍了CHAR与VARCHAR字段类型的使用方法,并且给出了二者的对比以及适用场景。在实际生产情况,需要具体情况具体分析,合适的才是最好的,希望这篇文章能给到大家参考。
欢迎关注个人公众号『MySQL技术』
相关推荐
- 【推荐】一款开源免费、美观实用的后台管理系统模版
-
如果您对源码&技术感兴趣,请点赞+收藏+转发+关注,大家的支持是我分享最大的动力!!!项目介绍...
- Android架构组件-App架构指南,你还不收藏嘛
-
本指南适用于那些已经拥有开发Android应用基础知识的开发人员,现在想了解能够开发出更加健壮、优质的应用程序架构。首先需要说明的是:AndroidArchitectureComponents翻...
- 高德地图经纬度坐标批量拾取(高德地图批量查询经纬度)
-
使用方法在桌面上新建一个index.txt文件,把下面的代码复制进去保存,再把文件名改成index.html保存,双击运行打开即可...
- flutter系列之:UI layout简介(flutter ui设计)
-
简介对于一个前端框架来说,除了各个组件之外,最重要的就是将这些组件进行连接的布局了。布局的英文名叫做layout,就是用来描述如何将组件进行摆放的一个约束。...
- Android开发基础入门(一):UI与基础控件
-
Android基础入门前言:...
- iOS的布局体系-流式布局MyFlowLayout
-
iOS布局体系的概览在我的CSDN博客中的几篇文章分别介绍MyLayout布局体系中的视图从一个方向依次排列的线性布局(MyLinearLayout)、视图层叠且停靠于父布局视图某个位置的框架布局(M...
- TDesign企业级开源设计系统越发成熟稳定,支持 Vue3 / 小程序
-
TDesing发展越来越好了,出了好几套组件库,很成熟稳定了,新项目完全可以考虑使用。...
- WinForm实现窗体自适应缩放(winform窗口缩放)
-
众所周知,...
- winform项目——仿QQ即时通讯程序03:搭建登录界面
-
上两篇文章已经对CIM仿QQ即时通讯项目进行了需求分析和数据库设计。winform项目——仿QQ即时通讯程序01:原理及项目分析...
- App自动化测试|原生app元素定位方法
-
元素定位方法介绍及应用Appium方法定位原生app元素...
- 61.C# TableLayoutPanel控件(c# tabcontrol)
-
摘要TableLayoutPanel在网格中排列内容,提供类似于HTML元素的功能。TableLayoutPanel控件允许你将控件放在网格布局中,而无需精确指定每个控件的位置。其单元格...
- 12个python数据处理常用内置函数(python 的内置函数)
-
在python数据分析中,经常需要对字符串进行各种处理,例如拼接字符串、检索字符串等。下面我将对python中常用的内置字符串操作函数进行介绍。1.计算字符串的长度-len()函数str1='我爱py...
- 如何用Python程序将几十个PDF文件合并成一个PDF?其实只要这四步
-
假定你有一个很无聊的任务,需要将几十个PDF文件合并成一个PDF文件。每一个文件都有一个封面作为第一页,但你不希望合并后的文件中重复出现这些封面。即使有许多免费的程序可以合并PDF,很多也只是简单的将...
- Python入门知识点总结,Python三大数据类型、数据结构、控制流
-
Python基础的重要性不言而喻,是每一个入门Python学习者所必备的知识点,作为Python入门,这部分知识点显得很庞杂,内容分支很多,大部分同学在刚刚学习时一头雾水。...
- 一周热门
-
-
C# 13 和 .NET 9 全知道 :13 使用 ASP.NET Core 构建网站 (1)
-
因果推断Matching方式实现代码 因果推断模型
-
面试官:git pull是哪两个指令的组合?
-
git pull命令使用实例 git pull--rebase
-
git 执行pull错误如何撤销 git pull fail
-
git pull 和git fetch 命令分别有什么作用?二者有什么区别?
-
git fetch 和git pull 的异同 git中fetch和pull的区别
-
git pull 之后本地代码被覆盖 解决方案
-
还可以这样玩?Git基本原理及各种骚操作,涨知识了
-
git命令之pull git.pull
-
- 最近发表
- 标签列表
-
- git pull (33)
- git fetch (35)
- mysql insert (35)
- mysql distinct (37)
- concat_ws (36)
- java continue (36)
- jenkins官网 (37)
- mysql 子查询 (37)
- python元组 (33)
- mysql max (33)
- vba instr (33)
- mybatis 分页 (35)
- vba split (37)
- redis watch (34)
- python list sort (37)
- nvarchar2 (34)
- mysql not null (36)
- hmset (35)
- python telnet (35)
- python readlines() 方法 (36)
- munmap (35)
- docker network create (35)
- redis 集合 (37)
- python sftp (37)
- setpriority (34)