数据结构论坛

首页 » 分类 » 定义 » MySQL教程之MySQL数据类型详解
TUhjnbcbe - 2025/4/27 16:12:00

前言

很久没写文章,也有博友在我的有些文章中留言,希望我可以写一些文章,公司项目一直很忙,但是每天也尽量腾出一些时间写一些东西,主要针对工作中一些常用的知识点系统性的梳理(可能我们在工作中只是纯粹的使用而已,不会去进行总结、归纳)。

本文写的内容是MySQL数据类型,之前写MySQL系列文章的时候一直忽略的一个知识点,现在想来,我们学习一门语言,无非从两个方面入手:

基本语法,有了语法,我们才可以组织逻辑数据类型,即在特定场景下选择合适的数据类型,到底是用整型还是浮点型还是字符串,每种数据机构占多少字节,最大值是多少。这点只针对强类型的语言,像js这种弱类型的语言,是不需要考虑这一点的

希望通过一篇文章的梳理,可以把MySQL数据结构这块都归纳清楚。

整型

先从最基本的数据类型整型说起,首先用一张表格归纳一下:

即使是带符号的BIGINT,其实也已经是一个天文数字了,什么概念,我们随便举下例子:

以byte为例可以表示GB--TB--PB以毫秒为例可以表示年

所以从实际开发的角度,我们一定要为合适的列选取合适的数据类型,即到底用不用得到这种数据类型?举个例子:

一个枚举字段明明只有0和1两个枚举值,选用TINYINT就足够了,但在开发场景下却使用了BIGINT,这就造成了资源浪费简单计算一下,假使该数据表中有W数据,那么总共浪费了W字节也就是6.7M左右,如果更多的表这么做了,那么浪费的更多

要知道,MySQL本质上是一个存储,以Java为例,可以使用byte类型的地方使用了long类型问题不大,因为绝大多数的对象在程序中都是短命对象,方法执行完毕这块内存区域就被释放了,7个字节实际上不存在浪不浪费一说。但是MySQL作为一个存储,8字节的BIGINT放那儿就放哪儿了,占据的空间是实实在在的。

最后举个例子:

droptableifexiststest_tinyint;

createtabletest_tinyint(

numtinyint

)engine=innodbcharset=utf8;

insertintotest_tinyintvalues(-);

insertintotest_tinyintvalues();

执行第7行的代码时候报错Outofrangevalueforcolumnnumatrow1,即很清楚的我们可以看到插入的数字范围越界了,这也同样反映出MySQL中整型默认是带符号的。

把第3行的num字段定义改为numtinyintunsigned第7的插入就不会报错了,但是第6行的插入-又报错了,因为无符号整型是无法表示负数的。

整型(N)形式

在开发中,我们会碰到有些定义整型的写法是int(11),这种写法从我个人开发的角度看我认为是没有多大用,不过作为一个知识点做一下讲解吧。

int(N)我们只需要记住两点:

无论N等于多少,int永远占4个字节N表示的是显示宽度,不足的用0补足,超过的无视长度而直接显示整个数字,但这要整型设置了unsignedzerofill才有效

下面举个例子,写一段SQL:

droptableifexiststest_int_width;

createtabletest_int_width(

aint(5),

bint(5)unsigned,

cint(5)unsignedzerofill,

dint(8)unsignedzerofill

)engine=innodbcharset=utf8;

insertintotest_int_widthvalues(1,1,1,);

select*fromtest_int_width;

从上面的两点,我们应该预期结果应该是1,1,,

我们看一下结果:

不符合预期是吧,因为这个问题我也有过困扰,后来查了一下貌似是Navicat工具本身的问题,我们使用控制台就不会有这个问题了:

不过实际工作场景中反正我是没有碰到过指定zerofill的,也不知道具体应用场景,如果有使用这种写法的朋友可以留言告知具体在哪种场景下用到了这种写法。

浮点型

整型之后,下面是浮点型,在MySQL中浮点型有两种,分别为float、double,它们三者用一张表格总结一下:

下面还是用SQL来简单看一下float和double型数据,以float为例,double同理:

droptableifexiststest_float;

createtabletest_float(

numfloat(5,2)

)engine=innodbcharset=utf8;

insertintotest_floatvalues(1.);

insertintotest_floatvalues(1.);

insertintotest_floatvalues(10.);

insertintotest_floatvalues(.);

insertintotest_floatvalues(0.);

insertintotest_floatvalues(00.);

insertintotest_floatvalues(000.);

select*fromtest_float;

显示结果为:

从这个结果我们总结一下float(M,D)、double(M、D)的用法规则:

D表示浮点型数据小数点之后的精度,假如超过D位则四舍五入,即1.四舍五入为1.23,1.四舍五入为1.24M表示浮点型数据总共的位数,D=2则表示总共支持五位,即小数点前只支持三位数,所以我们并没有看到0.23、00.、000.这三条数据的插入,因为插入都报错了

当我们不指定M、D的时候,会按照实际的精度来处理。

定点型

介绍完float、double两种浮点型,我们介绍一下定点型的数据类型decimal类型,有了浮点型为什么我们还需要定点型?写一段SQL看一下就明白了:

droptableifexiststest_decimal;

createtabletest_decimal(

float_numfloat(10,2),

double_numdouble(20,2),

decimal_numdecimal(20,2)

)engine=innodbcharset=utf8;

insertintotest_decimalvalues(.66,89900.66,89900.66);

insertintotest_decimalvalues(.66,899000.66,899000.66);

运行结果为:

看到float、double类型存在精度丢失问题,即写入数据库的数据未必是插入数据库的数据,而decimal无论写入数据中的数据是多少,都不会存在精度丢失问题,这就是我们要引入decimal类型的原因,decimal类型常见于银行系统、互联网金融系统等对小数点后的数字比较敏感的系统中。

最后讲一下decimal和float/double的区别,个人总结主要体现在两点上:

float/double在db中存储的是近似值,而decimal则是以字符串形式进行保存的decimal(M,D)的规则和float/double相同,但区别在float/double在不指定M、D时默认按照实际精度来处理而decimal在不指定M、D时默认为decimal(10,0)

日期类型

接着我们看一下MySQL中的日期类型,MySQL支持五种形式的日期类型:date、time、year、datetime、timestamp,用一张表格总结一下这五种日期类型:

下面我们还是用SQL来验证一下:

droptableifexiststest_time;

createtabletest_time(

date_valuedate,

time_valuetime,

year_valueyear,

datetime_valuedatetime,

timestamp_valuetimestamp

)engine=innodbcharset=utf8;

insertintotest_timevalues(now(),now(),now(),now(),now());

看一下插入后的结果:

MySQL的时间类型的知识点比较简单,这里重点

1
查看完整版本: MySQL教程之MySQL数据类型详解