MySQL数据类型

MySQL数据类型

  • 数据类型分类
    • 数值类型
      • tinyint 类型
      • bit类型
    • 小数类型
      • float
      • decimal
    • 字符串类型
      • char
      • varchar
      • 4.3.3 char和varchar比较
    • 日期和时间类型
    • enum 和set
      • enum
      • set
      • 集合查询使用find_ in_ set函数

数据类型分类

MySQL数据类型_第1张图片
注意: 图中类型不区分大小写。

数值类型

MySQL数据类型_第2张图片

tinyint 类型

先创建一个数据类型带有tinyint类型的表结构:
MySQL数据类型_第3张图片
现在我们创建了一个表结构,里面的字段含有tinyint类型,现在我们来测试一下tinyint是否如书上说的那样只能插入-128~127之间的数字;
MySQL数据类型_第4张图片
我们发现只要我们插入正常范围之内的数字都是没有问题的,接着我们来插入一下合法范围之外的数值:
MySQL数据类型_第5张图片
我们可以看到,在MySQL中对于超出合法范围的数值,MySQL不会像高级语言那样采取截断的方式来存储数据,而是直接暴力的不让其插入进去,这也就保证了插入进MySQL表中的数据都是合法的数据,这也就进一步限制了程序员在插入数据时必须验证数据的合法性!

对于数值类型来说当我们直接使用类型名的时候表示使用的是该类型的有符号类型,就比如上面的tinyint 我们是直接使用的tinyint这个类型,那么这个裸的tinyint类型就是默认为有符号类型!如果我们想要使用数值类型的无符号类型,那么我们需要在定义字段的时候在类型后面加上unsigned 关键字修饰,eg:
MySQL数据类型_第6张图片
紧接着我们也来验证以下无符号tinyint的边界测试:
MySQL数据类型_第7张图片

对于其它smallint 、mediumint、int、begint都是一样的,读者可以下来自行测试!

bit类型

基本语法:
colname bit(m);
m为bit位位数,m取值从1~64,如果m被忽略那么bit的默认位数是1;
eg:
先创建一个含有bit类型的表结构:
MySQL数据类型_第8张图片
现向其里面插入数据:
MySQL数据类型_第9张图片
从最后的输出界面我们可以看到如下现象:
1、values(‘倒计时’,1)和values(‘作战时’,0)这两组数据成功插入表中!
2、values(’小学生‘,2)和values(‘小学生’,3)这两组数据失败插入表中!这是为什么?
3、既然values(‘倒计时’,1)和values(‘作战时’,0)成功插入表中,那么我们就应该在表中看到flag那一列的值分别为0、1啊,可是为什么我们什么也没看见?

首先我们先来解决第一个问题:
根据我们之前对于bit类型的了解,当我们不指定bit类型的位数的时候,bit默认位数是1位,因此此时bit类型能表示的十进制范围就是0~1,因此凡是flag范围在0 ~1之内的values组都能被成功插入进表中,values(’小学生‘,2)和values(‘小学生’,3)这两组数据的falg都超出了此时flag的合法范围,因此会表现出插入失败!
接着我们来解决第二个问题:
values(‘倒计时’,1)和values(‘作战时’,0)确实是插入成功了,但是最后显示flag的时候是以flag的阿斯克码字符的形式来显示的,而对于十进制0、1的阿斯克吗字符都是不可显示字符,因此最后显示出来过后我们会什么也看不见!
如何证明?
我们可以将flag的bit位数改大一点,比如改成8位,然后插入一个flag=65的数据,按照我们之前的理论,那么最后显示的时候就应该以65的阿斯克吗字符显示,而65的阿斯克吗字符是’A‘,也就是说如果我们插入一组数据flag=65过后,在输出表结果,如果能看到’A‘那么就说明MySQL在显示bit类型的字段的时候确实是以阿斯克吗字符的形式来展示的;
开始展示:
1、修改flag的属性:
在这里插入图片描述
2、展示修改过后的结果:
MySQL数据类型_第10张图片
3、插入values(‘test’,65)数据:
在这里插入图片描述
4、验证结果:
MySQL数据类型_第11张图片
结果确实如我们所想的一样,因此MySQL在显示bit类型的值的时候使用该值的阿斯克码字符来显示的;

小数类型

float

语法:
colname float (m,n);
m:指定显示长度,不包含小数点;
n:指定小数位数;
占用4字节;
m上限是24,默认10;n上限是12,默认是2;
eg:
小数:float(4,2)表示的范围是-99.99 ~ 99.99,MySQL在保存值时会进行四舍五入。
先创建一个含有float数据段的表;
MySQL数据类型_第12张图片

现在插入一些数据:
MySQL数据类型_第13张图片

以上都是正常插入,我们接下来来一些不正常插入:
MySQL数据类型_第14张图片
我们插入的11.213、11.215命名长度已经超过4了为什么还能插入进去了?
实际上在对于浮点数的插入的时候没有那么严格,MySQL会尽可能的将浮点数转换为可以插入的形式,就比如上面的11.213虽然长度超了,但是经过四舍五入过后可以变成11.21这是一个合法的数字,因此会将其四舍五入过后的数字插入进去,11.215同理!
那么有没有经过四舍五入变化过后都不能进行插入的呢?
当然有:
在这里插入图片描述
就比如:99.999就不行,99.999经过四舍五入过后就是100.00,显然无法保证长度!
99.998亦是如此!
而对于这些四舍五入过后都不能进行插入的数据,MySQL才会报错!
当然float默认是有符号的,因此我们插入一些负数也是可以的:
MySQL数据类型_第15张图片
当然如果想使用无符号float,那么在定义的时候只需要在float后面加上unsigned修饰即可!
double也是如此!

decimal

语法:
decimal(m, d) [unsigned] : 定点数m指定长度,d表示小数点的位数
m上限:65,默认10;n上限:30,默认0;

  1. decimal(5,2) 表示的范围是 -999.99 ~ 999.99
  2. decimal(5,2) unsigned 表示的范围 0 ~ 999.99
  3. decimal和float很像,但是有区别:
  4. float和decimal表示的精度不一样,精度排名:float

float、double、decimal精度比较:
MySQL数据类型_第16张图片
将float、double、decimal的长度和精度都设为一样,然后插入相同的数据:
MySQL数据类型_第17张图片
很明显float出现了精度丢失,原数是12.123456789…经过float保存过后变为了12.123456954956,中间的78明显丢失了,而在看看double和decimal很明显精度都保存的比较好;
综上所述:如果在某些场景下需要保持较高的精度的话,建议选择double、decimal类型;如果是银行这种单位的话建议选择decimal这种精度最高的类型!

字符串类型

char

语法:
colname char(L)
L:表示固定长度字符串,表示可以存储L个的字符!L上限255;
注意我这里说的是L个字符不是字节! 下文我将细谈这两者说辞的差别!
eg:
创建一个带有char类型的表:
MySQL数据类型_第18张图片
现在进行一些插入操作:
MySQL数据类型_第19张图片
现在我们来插入一些非法的操作:
MySQL数据类型_第20张图片
我们可以看到我们本次插入的长度已经超过了当如我们设定的name(10)的限制,因为当前是使用的utf8编码,在utf8中一个汉字的大小是3字节!很明显本次插入了6个汉字也就是总共插入了18字节,18>10完全都已经超出了我们当初对于name字段的设定,为什么还能插入成功?
这就与我们刚开始的时候讲的char(L),这个L的含义有关系了,L表示能存储的字符的最大个数!注意是个数,不是字节! 在utf8中是3个字节表示一个字符的,为此在utf8编码中我们看到的符号都是一个字符!那么照这样理解,我们当初设定的name char(10),也就表示能最多够容纳10个字符,也就是最多能够容纳30字节的数据!为此当我们插入超出10个字符之外的字符串时就应该插入失败,eg:
MySQL数据类型_第21张图片
果然,我们:
insert into person values('123456778901',1259);
insert into person values('在吗吃了吗你好啊我爱你',1259);
insert into person values('这是一条test语句...',1259);
都失败了,因为’12345678901’的长度已经超过了10个字符,name字段装不下了,其它插入语句也是一样的!

varchar

语法:
colname varchar(L);
L:可变字符串,L表示字符串的长度,varchar能使用的上限是 65535字节!;
eg:
我们就先来创建一个带有varchar属性的表呗:
MySQL数据类型_第22张图片
插入一些语句试试:
MySQL数据类型_第23张图片
插入成功!
接着我们来进行一些非法操作:
MySQL数据类型_第24张图片
我们可以发现一旦我们插入的字符个数超过设定的值那么就无法在进行正确插入了,那么这些功能呢都和char一样啊,varchar有什么独特的地方吗?

varchar名字都叫变长字符串,说明所存储的字符串的长度是实际变化的,就是说利用varchar来存储的字符串的时候,你给valchar(L)设置的L,是表示该varchar最多能容纳L个字符,超过了就不行,但是我们在实际应用中是不可能每次都刚好使用的L个字符啊,有可能我们实际只用到了L-1,L-2,L-3…个字符,为此varchar就会为你分配实际所使用的字符个空间,举个例子:varchar(L),现在我们定义了一个最大字符个数为L的varchar类型,但是我们在实际使用中插入的字符串只使用了L-6个字符的空间,那么MySQL就会用L-6个字符的空间来实际存储我们的字符串,并不会为我们分配L个字符空间,这样的话能够有效避免空间浪费!
而对于char类型来说,char(L),L也表示char类型最多能够容纳L个字符的空间,我们实际中也有可能只用到了L-5个字符的空间,但是char类型就没有varchar那么细致,char类型是不关心用户传入的字符串实际使用了多少个字符空间的,它只管给你开L个字符的空间,反正空间给你开好了,你用一点点也给你开L个字符的空间,你用多了就给你报错,举个例子:char(L),实际我们的字符串可能只用了L-5个字符的空间,char不管,char还是我行我素,我还是给你开L个字符的空间,像char类型这样做的话,那么很明显是会造成空间浪费的,但是char类型效率高啊!因为char类型不需要关心用户实际用了多少空间,减少了关心成本;而varchar虽然有效的促进了空间的有效利用,但是这个有效利用是有成本的,也就意味着你varchar是必须分出一部分“精力”来管理字符串实际所占用空间的,效率自然就下去了!

再举个简单的形象一点的例子:
char 就相当于 C++中的char arr[N]定长字符数组;
varchar 就相当于C++中的string 变长字符串;

说明:
前面我们说了varchar也是有上限的,varchar的上限是65535字节,注意这里说的是字节不是字符!
因此针对与不同的编码系统varchar 能存储的上限字符个数也是不一样的!
同时varchar 既然是变长数组,它怎么知道当前用户的字符串实际用了多少个字符的空间?
很显然varchar有一个空间是专门记录实际字符个数的,事实也确实如此,varchar 会使用1~3字节的空间来记录实际的字符个数!
也就是说再varchar存储的上限65535字节中是有1~3字节来记录实际使用字符的大小的!
因此varchar实际用来存储数据的只有65535-3=65532个字节,在utf8中一个字符3字节,也就是说在utf中varchar最多能偶存储65532/3=21,844个字符的空间!
而在gbk中一个字符是2字节,也就是在gbk中最多能存储32,766个字符!
我们可以下来验证:
在utf8编码中:
在这里插入图片描述
在gbk中:

在这里插入图片描述

4.3.3 char和varchar比较

MySQL数据类型_第25张图片

如何选择定长或变长字符串?

  1. 如果数据确定长度都一样,就使用定长(char),比如:身份证,手机号,md5
  2. 如果数据长度有变化,就使用变长(varchar), 比如:名字,地址,但是你要保证最长的能存的进去。
  3. 定长的磁盘空间比较浪费,但是效率高。
  4. 变长的磁盘空间比较节省,但是效率低。
  5. 定长的意义是,直接开辟好对应的空间
  6. 变长的意义是,在不超过自定义范围的情况下,用多少,开辟多少

日期和时间类型

常用的日期有如下三个:

  1. date :日期格式’yyyy-mm-dd’ ,占用三字节
  2. datetime 时间日期格式 ‘yyyy-mm-dd HH:ii:ss’ 表示范围从 1000 到 9999 ,占用八字节
  3. timestamp :时间戳,从1970年开始的 yyyy-mm-dd HH:ii:ss 格式和 datetime 完全一致,占用
    四字节(该时间是变化的);

eg:具体来使用看看:
MySQL数据类型_第26张图片
从表结构我们都可以看出来,timestamp是支持缺省的,也就是说当我们插入数据时不对d3这一列数据进行插入的时候,MySQL会使用当前时间来作为d3这一列的内容,同时在EXtra这一列我们也可以青清楚的看到,当我们对这个表中的任何一行数据进行修改时都会影响当前行的timestamp这一列,timestamp都会更新为当前的最新时间!
接着我们来插入几个数据试试:
MySQL数据类型_第27张图片
同时如果现在我们进行更新操作的话,那么对应的被更新的哪一行的d3数据会被自动更新为当前的最新时间:
MySQL数据类型_第28张图片

date:应用场景:生日、纪念日
datetime:入职时间、身份证申请时间…
timestamp:文件的最近一次修改时间、最近一次修改评论的时间…

enum 和set

enum

enum语法:(单选类型)
colname enum('选项1','选项2','选项3',...);
当我们插入enum字段的时候只能从我们美剧出来的选项中选择一个来进行插入,如果选择选项之外的选项或者选出选项中的多个选项出来进行插入都会失败!
当然在实际插入的时候我们既可以直接使用选项来进行插入,也可以利用选项对应的编号来进行插入
这些编号从1开始;
eg:
选项1对应的编号是1;
选项2对对应的编号是2;

如果我们要想一个枚举类型中插入的话,有两种插法:
比如插入一个选项1:
insert into tablename values(‘选项1’)或者insert into tablename values(1);
两种插入方式都可:
eg:
在这里插入图片描述
比如我们正常插入:
MySQL数据类型_第29张图片
我们再来一些非法插入:
mysql> insert into t4 values('黑色'); ERROR 1265 (01000): Data truncated for column 'color' at row 1 //插入不存在的颜色会报错!
mysql> insert into t4 values('红色,白色'); ERROR 1265 (01000): Data truncated for column 'color' at row 1 //插入多个颜色也不允许,一次只能插入一个合法选项;
mysql> insert into t4 values(123); ERROR 1265 (01000): Data truncated for column 'color' at row 1 //插入超出枚举范围的编号也是不可以!

set

语法:(多选类型)
colname set('选项值1','选项值2','选项值3', ...);
该设定只是提供了若干个选项的值,最终一个单元格中,设计可存储了其中任意多个值,
同时set也支持使用数字来进行插入,但是set所支持的数字的方式与enum所支持的数字的方式不一样,set是将选项集合当作一个位图来看的,第一个比特位表示选项1,第二个比特位表示选项2…
比特位内容表示是否需要插入该选项,就比如:我现在想要插入选项1和选项2,那么有以下两种插法:
insert into tablename values(‘选项1,选项2’);或者
insert intp tablename values(3);//因为要插入选项1和选项2只需要讲位图的第一个比特位和第二个比特位置1即可,换成十进制就是3;
eg:
MySQL数据类型_第30张图片
现在进行正常插入:
MySQL数据类型_第31张图片
非法插入:
MySQL数据类型_第32张图片
mysql> insert into t5 values(32); ERROR 1265 (01000): Data truncated for column 'hobby' at row 1 //32对应的位图:100000,第六个比特位被置1,表示要插入第6个位置的选项,可是整个选项也就5个,很明显越界了;
mysql> insert into t5 values('dkdsjsf'); ERROR 1265 (01000): Data truncated for column 'hobby' at row 1 //插入不存的选项也会失败!

集合查询使用find_ in_ set函数

find_in_set(sub,str_list) :如果 sub 在 str_list 中,则返回下标;如果不在,返回0;
str_list 用逗号分隔的字符串。

eg:
现有一张表,表中有一些数据,表结构如下:
MySQL数据类型_第33张图片
表中数据:
MySQL数据类型_第34张图片
现在我想要筛选出爱好为足球的数据,注意我这里的表述是爱好为足球,不是包含足球应该怎么做呢?
select * from votes where hobby='足球';
MySQL数据类型_第35张图片
这是符合我们预期的;
那如果现在我们项要查询一下爱好中包含足球和篮球的数据呢?
MySQL数据类型_第36张图片
是如上指令吗?
显然不是上面的指令的意思是筛选出爱好为’足球,篮球’的数据!注意将’ '里面的数据看成一个整体,然后MySQL就拿着这个整体字符串去匹配,也就会匹配到刘备这一栏的数据,可是貂蝉里面也含有足球和篮球啊,很明显上面的查询方式有漏洞
可是我们应该如何做才能查询出hobby中即包含足球又包含棒球的数据呢?
find_ in_ set闪亮登场…
MySQL数据类型_第37张图片

你可能感兴趣的:(MySQL,mysql,c++,linux,数据库)