💖作者:小树苗渴望变成参天大树🎈
🎉作者宣言:认真写好每一篇博客💤
🎊作者gitee:gitee✨
💞作者专栏:C语言,数据结构初阶,Linux,C++ 动态规划算法🎄
如 果 你 喜 欢 作 者 的 文 章 ,就 给 作 者 点 点 关 注 吧!
文章目录
- 前言
- 一、数据类型的分类
- 二、 数值类型
- 2.1 整型
- 2.2bit类型
- 2.3小数类型
- 2.3.1float
- 2.3.2decimal
- 三、文本、二进制类型
- 3.1 char
- 3.2varchar
- 3.3char和varchar的区别
- 四、日期和时间类型
- 五、String类型
- 5.1enum
- 5.2set
- 六、总结
前言
今天我们开始讲解数据类型,相比较语言,我们的sql中的数据类型和语言的数据类型有相近之处,但是也有不同之处,所以博主会通过很多例子给大家看看这些数据类型和语言的差异,而且数据类型就代表我们存储数据的类型,所以说数据类型还是非常重要的,也希望读者要理解这些数据类型,才能更好的操作我们的数据库,话不多说,我们开始进入正文。
一、数据类型的分类
标红的博主一会都会介绍的,大家先看看类型对应的说明,有了语言数据类型的基础,大家应该不难理解sql的数据类型。
二、 数值类型
2.1 整型
我们以tinyint为例,其他的都是相同的用法
我们使用desc查看到我们的num对应的数据类型是tinyint(4),这里面的数据先不用管,后面有机会在说,我们往里面插入一些数据,来测试一样数值越界的实验:
通过实验我们发现一旦数据不符合类型规定的范围,就插入失败。
- 如果我们向mysql特定的类型中插入不合法数据,mysql一般都是直接拦截我们,不让我们做对应的操作
- 反过来,如果我们已经有数据被成功插入到MySQL中,一定插入的时候是合法的。
所以mysql中,一般而言,数据类型本身也是一种约束(后面有单独介绍约束的话题) ,约束本身是倒逼程序员正确的操作数据库,进行正确的插入,所以约束,本质是约束使用者,另外,如果你不是一个很好的使用者,mysql也能保证数据插入的合法性,同样的,我们讷讷感保证数据库中的数据是可预期的完整的
通过我们上面的例子我们知道了数据类型的作用,所以这也让大家可以更加认真的去学习数据类型,上面的说明:
· 在MySQL中,整型可以指定是有符号的和无符号的,默认是有符号的。
· 可以通过UNSIGNED来说明某个字段是无符号的
我们不写unsigned默认就是无符号的,我们来看看加上什么效果:
通过上面的例子我们看到tinyint有符合的取值范围是-128-127,无符合的取值范围是0-255,这个大家应该知道怎么回事,其余的关于整型的其他数据类型和这个都是一样的使用,只是存储的数据范围不一样而已。
注意:为什么要设计这么对存相同类型的数据类型?
上面我们存储整型有五个,每一种都有自己的使用场景,因为数据库他是需要存放海量数据的,所以给每个数据的时候空间就要合理起来,次啊能更好的节省空间,例如,年纪使用tinyint就是存储,你非得使用bigint,确实可以存储,但是这样就导致每一条数据又很多字节浪费了,所以我们要看存储的数据来确定使用那种数据类型最好,后面介绍的每一类数据类型可能都不止一种,原因就是这个,给更复杂的数据提供合适的使用场景。
2.2bit类型
bit[(M)] : 位字段类型。M表示每个值的位数,范围从1到64。如果M被忽略,默认为1。
- 我们看到我们在定义字段的时候,使用bit(8)这个数据类型,就表示他有八个比特位可以用,通过插入的数据,我们看到插入到255就插入不了,而且我们发现负数插入不了,说明这个数据类型只能插入非负的数据,也不存在什么有符号无符号之说。
- 我们看到插入数据居然没有显示,插入255就有显示,原因是使用bit这个数据类型他是按照ASCII码对应的值显示的,而前几个插入的数据是我们看不到的效果,我们按照十进制的方式查询
select id hex(a) from t3
这样就可以看出来确实是有数据插入进去的。- 通过输入我们熟悉的字符来看结果
也符合我们的验证.
我们直接定义bit里面不带数字,默认就是一位,来看效果:
我们看到这样只能存储进去0,1这两个数,但我们只有两种状态的场景,使用这个数据类型就非常的合适 ,节省空间。
我们超过它规定的64位连表都会创建失败:
2.3小数类型
2.3.1float
float[(m, d)] [unsigned] : M指定显示长度,d指定小数位数,占用空间4个字节
float(4,2)表示的范围是-99.99 ~ 99.99,MySQL在保存值时会进行四舍五入。
来看案例:
我们看到我们的数据在超过位数的时候,会进行四舍五入,如果四舍五入之后的数超过范围了就也插入不成功,我们发现在显示中小数部分都是两位,但是所有位数最终不超过4位。
如果float(6,3),范围是-999.999-999.999
上面的是有符合的,我们的小数类型还有无符号,和整型一样,加unsigned。
我们看到小数的无符合是直接将负数那部分砍掉。范围是0-99.99。
我们直接定义不带括号里面的数字,那么我们的float可以存储更大的数。
我们发现我们的float在保存大点的数据的时候,就会出现精度丢失,所以我们引入下面的一个数据类型decimal
2.3.2decimal
decimal(m, d) [unsigned] : 定点数m指定长度,d表示小数点的位数
decimal(5,2) 表示的范围是 -999.99 ~ 999.99
decimal(5,2) unsigned 表示的范围 0 ~ 999.99
decimal和float很像,但是有区别:
float和decimal表示的精度不一样
发现decimal的精度更准确,因此如果我们希望某个数据表示高精度,选择decimal
decimal整数最大位数m为65。支持小数最大位数d是30。如果d被省略,默认为0.如果m被省略,默认是10,这个大家下去测试一样
建议:如果希望小数的精度高,推荐使用decimal。如银行
总结
小数还有一个是double用法都是一样的,无非是精度的差别,可以看最前面的一张图有范围说明
三、文本、二进制类型
3.1 char
**语法:**这个L设置多大,不管里面存的字符是不是少于Lmysql都给你分配L长度大小的空间给你存储数据
char(L): 固定长度字符串,L是可以存储的长度,单位为字符,最大长度值可以为255
案例:
通过结果我们看到,abc超过了设置,所以报错,在我们语言的数据类型,知道一个字符占一个字节,一个汉字占两个或者三个字节,我们在sql中,设置的char(2),应该是2个字节的带下,我设置一个汉字插入没问题,可以理解,但是为什么两个汉字也可以插入进去呢??原因是我们sql中的字符和语言的不一样,一个汉字也是占一个字符,不看你大小。所以上面设置的char(2)最多可以放两个字符,不是必须放两个字符,但也不要超过两个字符,我们的char最多可以设置255个字符,超过了表都创建不成功。
3.2varchar
语法:这个数据类型是根据你插入数据的大小,系统自动给你分配使用空间,但是插入的数据不要超过L这个长度。
varchar(L): 可变长度字符串,L表示字符长度,最大长度65535个字节
大家看到我们的最大长度位65535个字节,所以一会肯定有坑,大家注意,先来看案例:
我们发现一个汉字也是一个字符,和char的效果是一样的,只不过可以存放的数据大小要比char大一些,我们在来看看varchar还有什么特性,在来看两者的区别。
上面我们测试了char的边界范围,和我们语法描述的是一样的,我们也来测试varchar:
我们发现都不行,这是为什么??
当我们的表的编码是utf8时,varchar(n)的参数n最大值是65532/3=21844[因为utf中,一个字符占
用3个字节],如果编码是gbk,varchar(n)的参数n最大是65532/2=32766(因为gbk中,一个字符
占用2字节)。所以我们最大长度的单位是字节,但是括号里面的单位是字符,所以要换算。
那为什么从65532开始计算,不从65535开始呢??
varchar长度可以指定为0到65535之间的值,但是有1 - 3 个字节用于记录数据大小,用三个字节的比特位就可以表示当前数据具体是使用了几个字符的空间大小。所以说有效字节数是65532。
为什么需要给出多余字节表示数据的大小??
因为varchar是根据数据类型的大小分配空间,所以读取的时候只有通过记录的大小让sql知道应该读取多大,相当于偏移量。不像char每次固定读取设置的大小
- 博主的字符集是utf8的,我们来看创建t9的时候,大小设置21844居然创建失败,原因是65535也是表中每一行的最大大小,我们创建t9的时候不止一个属性,还有一个id,占4个字节,所以我们需要少设置两个字符,相当于给了六个字节给id去使用,
- 我们创建t10的时候,因为就一个name字段,所以一行的所有空间都可以分配给他。
- 我们创建t11的时候大小设置程21845也不行,那保存数据大小的位置就没有了,我们设置只是数据的大小,保存数据的sql已经设置好了。这个大家要注意。
3.3char和varchar的区别
如何选择定长或变长字符串?
- 如果数据确定长度都一样,就使用定长(char),比如:身份证,手机号,md5
- 如果数据长度有变化,就使用变长(varchar), 比如:名字,地址,但是你要保证最长的能存的进去。
- 定长的磁盘空间比较浪费,但是效率高。
- 变长的磁盘空间比较节省,但是效率低。
- 定长的意义是,直接开辟好对应的空间
- 变长的意义是,在不超过自定义范围的情况下,用多少,开辟多少。
四、日期和时间类型
常用的日期有如下三个:
date :日期 'yyyy-mm-dd' ,占用三字节
datetime 时间日期格式 'yyyy-mm-dd HH:ii:ss' 表示范围从 1000 到 9999 ,占用八字节
timestamp :时间戳,从1970年开始的 yyyy-mm-dd HH:ii:ss 格式和 datetime 完全一致,占用四字节
我们发现我们就插入了t1和t2,但是t3也自动补充进去时间了,我们在来更新一下时间。
我们只修改了t1我们发现t2没有被修改,t3自动修改了,这就是datatime和timestmap的区别
使用场景:
我们的date一般只需要保存年月日的,比如博物馆购票,不需要规定什么时候来,在指定日期来就行了,其余两个,datetime不希望改变时间的时候,比如电脑开绝技时间,你只要不关机,每次想要查看本次开机时间都是一样的,timestmap一般在评论,你每次修改评论时间都会相对应的发生变化。
五、String类型
5.1enum
语法:
enum:枚举,“单选”类型;
enum(‘选项1’,‘选项2’,‘选项3’,…);
该设定只是提供了若干个选项的值,最终一个单元格中,实际只存储了其中一个值;而且出于效率考
虑,这些值实际存储的是“数字”,因为这些选项的每个选项值依次对应如下数字:1,2,3,…最多65535
个;当我们添加枚举值时,也可以添加对应的数字编号。
案例:
我们看到我们的枚举只能是单选,可以按照内容插入,也可以按照数字插入。不在枚举里面的内容插入不了,也算是一种约束。
说明: 不建议在添加枚举值,集合值的时候采用数字的方式,因为不利于阅读。
5.2set
语法:
set:集合,“多选”类型;
set(‘选项值1’,‘选项值2’,‘选项值3’, …);
该设定只是提供了若干个选项的值,最终一个单元格中,设计可存储了其中任意多个值;而且出于效率考虑,这些值实际存储的是“数字”,因为这些选项的每个选项值依次对应如下数字:1,2,4,8,16,32,…最多64个。
案例:
通过结果来看,我们的set是一个集合,是一个多选,但是不在集合里面插入不进去,也可以使用数字插入,但是和enum有差别,不是和位数一一对应,而是和位图对应,数字3不是羽毛球,3对应的是011,所以第一位和第二位为1,所以插入进去的是篮球和足球,这个大家要清楚。
查找数据
对于enum我们不用担心查找,因为是单旋,但是set是多选,我们的筛选语句只能严格匹配,不能找出所有的,我们在往表中插入一些数据:
查找爱好是羽毛球的人。我们发现查的不全,使用数字也不行,那我们应该怎么办,我们有了下面这个函数,没错,我们的sql中也是有函数:集合查询使用find_ in_ set函数
find_in_set(sub,str_list) :如果 sub 在 str_list 中,则返回下标;如果不在,返回0;str_list 用逗号分隔的字符串。
使用:
我们的集合查询函数一次只能查找一个元素在集合中的位置,找不到就返回0.
查询喜欢羽毛球的人并且查询喜欢羽毛球和足球的人:
相信大家学习到这里,对于enum和set应该学会了,大家下去多去来练习。
六、总结
对于数据类型,博主介绍都是常用的,够大家日常使用了,如果真的有场景这些数据类型适用不了,大家在1去搜一下有没有合适的数据类型,学号数据类型,才是学号数据库操作的第一步,大家一定要度过这一关。我们下一篇讲解表的约束。