文章目录
- [1. 数据类型分类](#1. 数据类型分类)
- [2. 数值类型](#2. 数值类型)
-
- [2.1 tinyint 类型](#2.1 tinyint 类型)
- [2.2 bit 类型](#2.2 bit 类型)
- [2.3 小数类型](#2.3 小数类型)
-
- [2.3.1 float 类型](#2.3.1 float 类型)
- [2.3.2 decimal](#2.3.2 decimal)
1. 数据类型分类

一共有这么多,其中标红的我们重点讲解,其它的类似的,我们简单介绍一下,大家以看就懂了
首先我们来看数值类型这个大类
2. 数值类型
先来看一看整形

我们看到有很多种,类似我们的熟悉的编程语言中的整形,它们的区别就是大小(size)不同,那对应的能表示的范围就不同,在不同的场景选择合适的类型使用
2.1 tinyint 类型
那么下面我们以tinyint为例重点进行讲解,其它几个整形用法是完全一样的(只是表示范围不同)
首先新建一个数据库test1
然后我们来建一个表t1
create table t1(num tinyint);
只有一列,列名为num,类型为tinyint
回看上面表格里对tinyint的介绍,使用的时候可以在后面加unsigned ,表明它是无符号数,不加默认为有符号数。
即在MySQL中,整型可以指定是有符号的和无符号的,默认是有符号的。
可以通过UNSIGNED来说明某个字段是无符号的
然后来插入一些数据,这里是有符号数,那tinyint一个字节,范围是-128~127
那我们来插入一下128和127试试:
insert into t1 values(-128);
不指明哪一列插入默认就是全列插入,当然该表也只有一列
没有问题,都插入成功了。
再来插入一些中间值:
没问题。
那插入一个不在范围内的:
当然不可以,并且报错已经告诉我们,是因为超出范围了
那下面我们再来试一下无符号数:
create table t2(num tinyint unsigned);
那此时num列的数据的取值范围就是0~255,如果超出范围同样不被允许
我们来试一下:
然后这里再给大家补充一些内容:
比如在我们的C/C++中,我们写这样一条语句:
char ch=1234567;
显然,这个值肯定是放不进去的,因为超出范围了,char类型一个字节,范围也是-128~127
但是我们这样写,传统的编译器一般是不会报错的
最多会有警告,而且它自动会发生截断 (或者有些其它情况发生隐式类型转换),超出的部分直接不要了,然后存进去。
在语法层面它不会拦截我。
但是我们看到MySQL这里:
如果我们试图插入不合法的数据,MySQL会直接拦截我们,不让我们操作。
那反过来,已经成功插入到MySQL中的数据,它一定是合法的数据。
能够查出来的数据一定是在合法范围内的。
所以,对于MySQL,一般而言,数据类型本身也是一种"约束 ",当然约束我们后面会专门讲,这里可以作为一个引子。
那它就会倒逼我们使用者,进行正确的插入,所以约束的是我们使用者(即使你是一个什么都不懂的小白,你随便插入数据,MySQL也能保证最终插入进去的数据一定是合法的,因为不合法的直接被拦截了),这就保证了数据库中的数据是可预期的(一定在合法的范围内)、完整的(没有发生截断/类型转换)。
另外,通过上面的练习,我们发现一个细节:
MySQL中我们建立属性列的时候,是
名字在前 类型在后
num tinyint
跟我们熟悉的编程语言中的方式是反着来的
int x;
上面我们讲的是tinyint,但是其它类型也是一样,其它类型大家可以自己练习
为什么有这么多类型,其实就是在满足应用场景和节省资源之间做平衡 。
比如现在有一列要存年龄,那有没有必要用int呢?其实用个tinyint或tinyint unsigned完全足够了。
那我用int、bigint可以吗?当然也可以,但是没必要,而且浪费资源。
2.2 bit 类型
基本语法:
sql
bit[(M)]
位字段类型。M指定位数,范围从1到64。如果M被忽略,默认为1。前面我们说过,中括号中的是可选的
举例:
先来新建一个表t3
create table if not exists t3(id int,online bit(1));
有2列,第一列id,类型为int;
第二列nonline,这里我们指定一个为比特位(M=1),表示用户是否在线(1在线,0不在线,一个比特位就可以表示,一个比特位也只能表示0和1)
那下面我们来插入一些数据
没有问题(不过这里我们看到online列它默认是16进制显示的)
那一个比特位只能表示0或1,那我插入其它值呢?
当然就不行
也可以这样:
select id,hex(online) from t3;
HEX() 函数返回原始十六进制字符串,没有 0x 前缀
下面我来修改一下表,把online改为10bit:
修改表的操作我们上一篇文章讲过了
alter table t3 modify online bit(10);
那现在10个比特位,可表示的范围当然就更大了(0~1023)
当然也可以插入字符,但本质插入的是其对应的ANSCII码值
上面提到bit(M),M的范围是0~64
所以:
就不行,报错也提示max=64
另外,M忽略默认为1,也给大家演示一下
2.3 小数类型
2.3.1 float 类型
语法:
sql
float[(m, d)] [unsigned]//unsigned不带,默认有符号
float大小4个字节,M指定显示长度(总长度),d指定小数位数(小数点后的长度,即精度)
举例:
先来建表
create table if not exists t5( id int, salary float(4,2) );
有两列,id代表身份,salary代表薪水,salary的类型为(有符号)float(4,2),就代表总的显示长度为4,小数点后的位数长度为2
float(4,2)表示的范围是-99.99 ~ 99.99(有符号),MySQL在保存值时会进行四舍五入
我们来插入数据验证一下
插入成功
来试一些不合法的
肯定都不可以,范围超了,而且位数也超了,虽然最后一次插入100.0,总长度是4位,但是也不行。
因为float(4,2)就说明小数点后一定是两位,我们不写它也会补0,那加上前面的100三位,就是5位了 ,就超了,而且数值范围也是超的,所以肯定不行
另外上面还有一句话,MySQL在保存值时会进行四舍五入
我们来验证一下
再来看一组
前两个可以,因为舍掉了,存的是99.99,在范围内。后两个不行,因为要入,入完就超过99.99(最大值)了,所以插入失败
所以四舍五入的前提是要在范围内。
想让它表示的范围更大,那就修改后面括号里面的m,d。按照需要设定合适的值即可。
C/C++中浮点数都是有符号的,没有unsigned float或unsigned double即无符号浮点数这一说,而MySQL中FLOAT和DOUBLE可以有UNSIGNED属性。
ps:实际上MySQL的UNSIGNED FLOAT只是应用了值域约束(禁止负数),底层存储格式与有符号相同
下面我们来试一下float(m,d) unsigned
create table t6( id bigint, salary float(4,2) unsigned );
还是float(4,2),只不过这次是无符号数
那它的范围应该是多少?
范围是 0 ~ 99.99(就是把负数的部分砍掉了)
插入一些数据试试:
如果插入负数或超过范围,那肯定就不行
当然也会四舍五入
提问:如果float(6,3),范围是多少?
有符号 (SIGNED): -999.999 到 +999.999
无符号 (UNSIGNED): 0.000 到 999.999
我们知道,浮点数存的时候有些数值是不能被表示的很精确的(MySQL存浮点数当然也是二进制的形式),难免会有精度损失
我们来验证一下:
先来修改一下t6的表结构
alter table t6 modify salary float;
把salary的类型改为float,后面不带括号指明m和d,用默认的(默认的范围还是很大的)
来插入一些数据试一下
很明显是会有精度损失的。
还要double,就不详细介绍了,当然它的精度会比float更大。
2.3.2 decimal
语法:
sql
decimal(m, d) [unsigned] : 定点数m指定长度,d表示小数点的位数
decimal也是MySQL中的一种浮点数类型,那它跟float和double有什么区别呢?
decimal的精度更准确,因此如果我们希望某个数据表示的精度更高,选择decimal(上面我们也看了float是很容易发生精度损失的)
它的使用语法和我们上面介绍的float是一样的
下面我们就通过具体的案例来带大家熟悉一下decimal:
先来建张表
create table t7( f1 float(10,8), f2 decimal(4,2) );
有两列,类型分别是float和decimal,m和d是不同的
decimal(4,2),所以它的范围也是-99.99~99.99
而且float所具有的特性它肯定也都有(范围控制,四舍五入)
我们来插入一些数据试一下
没有问题,但是我们看到这里decimal发生四舍五入的情况有一个警告
精度损失警告:原始值有3位小数,存储时只有2位,有精度损失(float是没有的)
不过上面不是说跟float相比,decimal精度更高嘛,我们来验证一下:
对上面表结构进行一下修改
现在float和decimal的m和d是完全一样的(现在精度都是8位)
然后我们来插入一些一样的数据,对比一下两列的展示
我们看到,float这一列,虽然设定的精度是8位,我们插入的也是小数点后有8位,但是显示这里存进去的数据已经发生变化了,而decimal这一列存进去的是没有变化的
因此如果我们希望数据表示的精度更高,选择decimal
后面剩余的数据类型,下一篇继续...












































