【MySQL】数据类型(上)

文章目录

  • [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

后面剩余的数据类型,下一篇继续...

相关推荐
想唱rap3 小时前
MYSQL在ubuntu下的安装
linux·数据库·mysql·ubuntu
java1234_小锋3 小时前
MySQL中的乐观锁和悲观锁是什么?
mysql
robotx3 小时前
AOSP设备节点权限添加相关
android
顾林海3 小时前
Android文件系统安全与权限控制:给应用数据上把“安全锁”
android·面试·操作系统
青莲8433 小时前
Android 动画机制完整详解
android·前端·面试
城东米粉儿3 小时前
android 离屏预渲染 笔记
android
未知名Android用户4 小时前
Android自定义 View + Canvas—声纹小球动画
android
齐 飞4 小时前
快速删除mysql表中所有数据-TRUNCATE TABLE
数据库·mysql
_李小白4 小时前
【Android FrameWork】延伸阅读:AMS 的 handleApplicationCrash
android·开发语言·python