「前言」文章内容大致是数据库的数据类型。
「归属专栏」MySQL
「主页链接」个人主页
「笔者」枫叶先生(fy)
目录
一、数据类型分类
C/C++语言有自己的数据类型,MySQL也有自己的数据类型,常见的的数据类型如下:
注:带红色的是下面要讲解的类型
数据类型的作用:
- 决定了存储数据时应该开辟的空间大小。
- 决定了数据的取值范围。
二、数值类型
2.1 tinyint类型
接下来讲解数值类型的整型,整型的取值范围跟C/C++语言的数据类型取值范围都差不多,同样有有符号和无符号的区别
整型以tinyint为例
创建一个表,表当中包含一个tinyint类型的列,默认其为有符号类型
圆括号4,下一个篇章约束再谈,这里暂时不理会
tinyint类型占用1字节,有符号tinyint的取值范围为
-128~127
,进行插入数据
如果插入的数据不在-128~127范围,则不允许插入,报错:
下面是无符号tinyint范围测试
创建一个表,表当中包含一个tinyint类型的列,并指定其为无符号类型
tinyint类型占用1字节,无符号tinyint的取值范围为
0~255
,进行插入数据:
如果插入的数据不在
0~255
范围,则不允许插入,报错:
注意:向MySQL插入不合法的数据,MySQL会直接拦截我们的操作;如果我们已经将数据成功插入表中,那么插入的数据一定合法的。所以在MySQL中,数据类型本身就是一种约束。
从上面的例子也可以看出,MySQL表中建立属性列是列名字在前,类型在后
num(列名) tinyint(类型)
注意:尽量不使用unsigned,对于int类型可能存放不下的数据,int unsigned同样可能存放不
下,与其如此,还不如设计时,将int类型提升为bigint类型
以上便是tinyint的介绍,其他整型也类似,不再演示
2.2 bit类型
基本语法:
bit[(M)]: 位字段类型。M表示每个值的位数,范围从1到64。如果M被忽略,默认为1
注:[] 的部分可以省略
创建一个表,表当中包含一个int类型和一个bit类型,bit默认为1位
向表中插入数据,一个bit位只允许插入0,1
查看表的数据,发现bit类型不显示,根本原因是因为bit类型在显示时,是按照
ASCII
码对应的值进行显示的,有些字符是不可显示的
如果要查看该值,强转为十进制
修改表,改成 bit(10)
再次插入数据,结果证明确实是按
ASCII
码对应的值进行存储
bit(M),M最大值是64,如果超过了创建表就会失败
如果我们有这样的需求,只存放0或1,这时可以定义bit(1),这样可以节省空间
2.3 小数类型
2.3.1 float类型
语法:
float[(m, d)][unsigned]: M指定显示长度,d指定小数位数,占用空间4个字节
创建一个表,包含一个float(4,2)类型的列,默认其为有符号类型
float(4,2)表示的范围是
-99.99 ~ 99.99
,在该范围内可以插入数据,超过范围报错
尝试插入超过范围的
说明:MySQL在保存值时会进行四舍五入
即使输入多位小数,也会按指定的格式显示
注意:无符号float类型的取值范围,实际就是把对应有符号float类型中的负数部分砍掉了,因此float(4,2)的取值范围为0~99.99
还有一个问题要注意,float类型会精度丢失问题
2.3.2 decimal类型
语法:
decimal(m, d)[unsigned]: 定点数m指定长度,d表示小数点的位数
- decimal(5,2) 表示的范围是 -999.99 ~ 999.99
- decimal(5,2) unsigned 表示的范围 0 ~ 999.99
- 这点与float是一样的
decimal和float很像,但是有区别:float和decimal表示的精度不一样
测试精度
创建一个表,表当中分别包含一个float(10,8)的列和一个decimal(10,8)的列
向表当中插入数据,查表结果float则会存在一定的精度损失,decimal则没有
- float表示的精度大约是7位
- decimal整数最大位数m为65。支持小数最大位数d是30。如果d被省略,默认为0.如果m被省略, 默认是10(可能会受到MySQL版本影响)
decimal的精度更准确,因此如果我们希望某个数据表示高精度,可以选择decimal
2.4 字符串类型
2.4.1 char类型
语法:
char(L): 固定长度字符串,L是可以存储的长度,单位为字符,最大长度值可以为255
测试:
创建一个表,表当中包含一个char(2)列
插入数据,需要注意的是,在MySQL里,这里所说的字符并不与C/C++里面的字符相同,在MySQL里一个汉字也是一个字符
在不同编码中,一个字符所占的字节个数是不同的,比如utf8中一个字符占3个字节,而gbk中一个字符占2个字节
2.4.2 varchar类型
语法:
varchar(L): 可变长度字符串,L表示字符长度,最大长度65535个字节
测试:
创建一个表,表当中包含一个varchar(2)
插入数据,varchar在这与char没什么区别
varchar类型注意事项
关于varchar(len),len到底是多大,这个len值,和表的编码密切相关:
- varchar长度可以指定为
0到65535
字节之间的值,但是有1 - 3
个字节用于记录数据大小,所以说有效字节数是65532
- 当我们的表的编码是utf8时,varchar(n)的参数n最大值是
65532/3=21844
(因为 utf8 中,一个字符占用3个字节) - 如果编码是gbk,varchar(n)的参数n最大是
65532/2=32766
(因为gbk中,一个字符 占用2字节)
2.4.3 char和varchar比较
char和varchar比较
- char类型可存储字符上限为255,varchar类型可存储字符上限与表的编码格式有关。
- char(L)定义后,无论存储的字符串长度是否到达L,都会开辟用于存储L个字符的定长空间,如果存储的字符串长度超过L则会报错。
- varchar(L)定义后,会根据存储字符串的长度按需开辟空间,并且需要使用1-3字节的空间用于表示存储字符串的长度以及其他控制信息,如果存储的字符串长度超过L则会报错。
以utf8编码为例:
如何选择定长(char)或变长字符串(varchar)?
- 如果数据确定长度都一样,就使用定长(char),比如:身份证,手机号,md5
- 如果数据长度有变化,就使用变长(varchar), 比如:名字,地址,但是你要保证最长的能存的进去。
- 定长的磁盘空间比较浪费,但是效率高。
- 变长的磁盘空间比较节省,但是效率低。
- 定长的意义是,直接开辟好对应的空间
- 变长的意义是,在不超过自定义范围的情况下,用多少,开辟多少
2.5 时间日期类型
常用的日期有如下三个:
date
:日期yyyy-mm-dd
,占用三字节datetime
时间日期格式yyyy-mm-dd HH:ii:ss
表示范围从1000 到 9999
,占用八字节timestamp
:时间戳,从1970年开始的yyyy-mm-dd HH:ii:ss
格式和 datetime 完全一致,占用四字节
创建一个表,表当中包含date、datetime和timestamp三种时间日期类型的列
查看表结构可以看到,timestamp类型的t3列是不允许为空的,它的默认值为
CURRENT_TIMESTAMP
如果向表中插入数据,t3会自动更新到最新时间(无需手动插入)
向表中插入值
更新数据,时间戳会更新
2.6 enum和set
enum:枚举,“单选”类型;
enum('选项1','选项2','选项3',...);
- 该设定只是提供了若干个选项的值,最终一个单元格中,实际只存储了其中一个值(只允许选取其中的一个值)
- 出于效率考虑,这些值实际存储的是“数字”,因为这些选项的每个选项值依次对应如下数字:
1,2,3,....
,最多65535
个;当我们添加枚举值时,也可以添加对应的数字编号
set:集合,“多选”类型:
set('选项值1','选项值2','选项值3', ...);
- 该设定只是提供了若干个选项的值,最终一个单元格中,设计可存储了其中任意多个值(可以选取其中的一个或多个值)
- 出于效率考虑,这些值实际存储的是“数字”,因为这些选项的每个选项值依次对应如下数字:
1,2,4,8,16,32,....
,最多64个
注意:不建议在添加枚举值,集合值的时候采用数字的方式,因为不利于阅读
例子
创建一个调查表,表当中包含被调查人的姓名、性别(只选一个)和爱好(多个)
向表中插入记录时,被调查人的性别只能从男和女中进行二选一,被调查人的爱好可以从提供的若干个选项中进行多选一或多选多,多个爱好之间需要通过英文逗号隔开
可以通过数字设置enum
数字是从1开始,有几个值数字最大就是几,例如enum(‘男’, ‘女’),数字1代表男,数字2代表女,最大就是2,超过了范围则不允许插入
根本原因在于,MySQL出于效率考虑,这些值(比如男,女)实际存储的是“数字”,因为这些选项的每个选项值依次对应如下数字:
1,2,3,....
,最多
65535
个
可以通过数字设置set
在插入记录时,除了通过指明多个选项来设置爱好,还可以通过数字的方式来设置
使用数字插入并不是使用下标,使用的是位图的方式进行插入
例如:
'羽毛球','游泳','篮球','写代码' // 4个爱好
用比特位表示:0000
0001 (1)是羽毛球
0010 (2)是游泳
0011 (3)是羽毛球,游泳
0100 (4)是篮球
依次类推
1111 (15)则是'羽毛球','游泳','篮球','写代码'
注:虽然enum和set可以通过数字的方式进行设置,但严重不推荐这种做法,因为这样的SQL可读性太差
enum和set查找
如果想要筛选出调查表中的所有女的或男的,那么直接在筛选时指明
gender='女'
或者
gender='男'
即可
但如果要筛选出调查表中爱好包含游泳的就不能使用where了,这并不是我们想要的结果
集合查询使用find_ in_ set函数:
find_in_set(sub,str_list)
:如果 sub 在 str_list 中,则返回下标;如果不在,返回0;str_list
字符串是用逗号分隔的字符串
--------------------- END ----------------------
「 作者 」 枫叶先生
「 更新 」 2023.7.17
「 声明 」 余之才疏学浅,故所撰文疏漏难免,
或有谬误或不准确之处,敬请读者批评指正。
版权归原作者 枫叶先生 所有, 如有侵权,请联系我们删除。