上篇文章小编讲述了关于MySQL表的DDL操作,在那里我多次使用了MySQL的数据类型,但是我并没有去讲述MySQL的数据类型,想必各位读者已经很好奇MySQL的数据类型都有什么了,今天这篇文章我将会详细的去讲述MySQL的数据类型,希望可以为各位解惑。
在详细说明每个数据类型之间,我先来让各位看一看MySQL中有几种数据类型以及它们的分类(只截取了比较重要的一部分,还有一些我并没有展示出来,各位读者感兴趣可以去官方网站自行学习)。
上面的类型有很多种,不过很多我们在学C语言的时候就已经感到很熟悉了,就比如数值类型中的int类型,它就是我们在C语言学习的整型,这点MySQL和C语言还是一样的,当然MySQL和C语言还是有差异的地方的,就比如文本类型的中的char,在C语言中,它代表的是字符类型,也就是'A'、'B'等等的字符;而它在MySQL代表的事一个固定长度的字符串,各位千万不要把它的定义和C语言的混为一谈。下面我将从数值类型、文本。二进制类型。时间日类类型以及string类型这几个方面,详细讲述MySQL的数据类型以及它和编程语言的异同,帮各位避开这些认知陷阱。
上表就是我想要讲述的数值类型,此时我先简单的带着各位看下这个表,这个表大多数的都是和整型int相关的,之所以放到一起是因为我认为它们是有相似性的,当我讲述完其中几个以后,剩下的类型各位就可以自己去领悟了(绝对不是因为我偷懒),下面我来分别讲述一下这几种类型。
通过上表,我们可以简单的知道它所代表的范围是-128到127,因为它是占据一个字节,一个字节是八个比特位,所以它可以表示2^8也就是256个不同的值(从00000000到11111111);在计算机用补码表示有符号整数时,最高位为0表示正数(0到127),最高位为1表示负数(-1到-128),其中 10000000 这个特殊编码被定义为 -128,因此整体范围就是 -128 到 127。因此它的范围就是-128到127,可能有些读者好奇它的范围真的卡的那么严吗?不要急,下面我简单的进行范围的测试(里面涉及到表的DML的知识,这是我下一篇文章要讲述的,各位读者可以先期待着)。
此时我简单的建立一个表,这个表的名字是student,里面涉及学生的学号以及姓名(就这么简单就好了),下面是实现的代码(建议各位读者可以自行实现,之后再来和我的进行对照)。
create table student(
name varchar(20) #代表的是姓名
id tinyint
);#代表表的创建
此时我们可以先插入最大值试一试,因为我还没有讲述表的插入操作,所以各位知晓我的目的是把一个学生姓名为张三的,id为127;
insert into student values('张三',127);
此时可以看出插入成功了,下面我们查询我们插入的数据。同样的,这涉及到表的查询操作,我依旧不解释。
select * from student;
下面我们插入最小值试一下,插入一个姓名为李四,id为-128(有点奇怪)的数据。
insert into student values('李四',-128);
此时数据依然是插入成功了,我们依旧可以查询插入的数据。
select * from student;
此时我试着插入一个姓名为小禾,id为128的数据。
insert into student values('小禾',128);
正如我们所见,尝试插入超出 tinyint
范围(-128 到 127)的值导致了错误。这验证了整型的一个重要规则:当插入的值超出该整型定义的数值范围时,数据库系统会报错。 其他整型(如 smallint
, int
, bigint
)的核心机制与此完全相同,区别仅在于它们能容纳的范围大小不同。既然原理一致,我们就不再逐一赘述。接下来,让我们把目光转向另一种重要的数据类型——小数类型。
语法:
float[(m, d)] [unsigned] : M指定显示长度,d指定小数位数,占用空间4个字节
与整型不同,float
类型在定义时需要指定两个参数,语法为 float(M, D)
。下面我来详细解释这两个参数的含义和使用规则:
M
(总精度/显示宽度):代表该浮点数总共可以显示的最大数字位数(包括整数部分和小数部分的所有数字字符,不包括小数点本身和符号位)。
128.1
包含数字 1
,2
,8
,1
→ 总共 4 位数字
12.81
包含数字 1
,2
,8
,1
→ 总共 4 位数字
D
(小数位数/标度):代表该浮点数小数点后允许的最大位数。
128.1
的小数点后有 1 位数字 (1
)
12.81
的小数点后有 2 位数字 (81
)
M
和 D
定义的是上限值[敲重点]:实际存储的数字位数可以少于 M
,小数位数可以少于 D
,但不能超过
float
存储的是近似值而非精确值(这一点与整型完全不同)
下面我通过一个建表实例,展示 float
类型的使用规则:
-- 创建包含float(4,2)类型的测试表
CREATE TABLE product (
name VARCHAR(20), -- 产品名称
price FLOAT(4,2) -- 价格(总位数不超过4,小数位不超过2)
);
-- 有效数据:总位数4,小数位2
INSERT INTO product VALUES ('铅笔', 12.34); -- 数字:1,2,3,4 → 4位
-- 有效数据:总位数3<4,小数位1<2
INSERT INTO product VALUES ('橡皮', 8.5); -- 数字:8,5 → 2位(总位数不足)
-- 有效数据:边界值测试
INSERT INTO product VALUES ('笔记本', 99.99); -- 数字:9,9,9,9 → 4位
-- 超出总位数限制(5>4)
INSERT INTO product VALUES ('钢笔', 100.00);
-- 错误:总位数5 (1,0,0,0,0) > 4
-- 超出小数位限制(3>2)
INSERT INTO product VALUES ('尺子', 12.345);
-- 错误:小数位数3 > 2
-- 同时违反两项规则
INSERT INTO product VALUES ('文具盒', 123.45);
-- 错误:总位数5>4 且 小数位2>2?(实际D=2允许2位小数,但总位数超限)
SELECT * FROM product;
执行结果应显示:
+-----------+-------+
| name | price |
+-----------+-------+
| 铅笔 | 12.34 |
| 橡皮 | 8.50 | -- 自动补零显示
| 笔记本 | 99.99 |
+-----------+-------+
float
存储的是近似值,对精度要求高的场景(如金融计算)应使用 decimal
类型
-- 精度问题示例 INSERT INTO product VALUES ('计算器', 1.0 / 3.0); -- 存储为0.3333333432674408
(M,D)
,此时使用系统默认精度
CREATE TABLE temp (value FLOAT); -- 不指定参数
8.5
显示为 8.50
)
通过以上实例,各位读者可以清晰看到:float(4,2)
可以存储 12.34
(刚好满位)、8.5
(位数不足)和 99.99
(边界值),但拒绝 100.00
(总位数超限)和 12.345
(小数位超限)。这种灵活的位数控制使 float
成为处理科学计算和大范围数值的理想选择,但切记它的近似特性可能带来精度问题!
在金融计算、货币交易等需要绝对精度的场景中,decimal
类型是 MySQL 中最值得信赖的数据类型。与 float
的近似存储不同,decimal
以固定精度存储数值,确保计算结果完全精确,避免浮点数常见的舍入误差问题。
M
(总精度):总位数(整数部分+小数部分),范围 1-65
D
(小数位数):小数点后的位数,范围 0-30 且 D ≤ M
decimal(5,2)
可存储 123.45
(5位总数,2位小数)
decimal(18,9)
需要 9字节(每部分9位,各需4字节,共8字节?实际需要9字节)
CREATE TABLE bank_account (
account_id INT PRIMARY KEY,
owner_name VARCHAR(50),
-- 总位数10位,其中2位小数(最大存储:99,999,999.99)
balance DECIMAL(10,2)
);
-- 初始存款:精确存储
INSERT INTO bank_account VALUES (1001, '张三', 10000.00);
-- 存款利息计算(年化3.5%,按日计息)
UPDATE bank_account
SET balance = balance * (1 + 0.035/365)
WHERE account_id = 1001;
-- 查询结果(显示精确计算结果)
SELECT * FROM bank_account;
输出结果:
+------------+------------+--------------+
| account_id | owner_name | balance |
+------------+------------+--------------+
| 1001 | 张三 | 10000.958904 | -- 精确到小数点后6位
+------------+------------+--------------+
-- 最大允许值(符合decimal(10,2))
INSERT INTO bank_account VALUES (1002, '李四', 99999999.99); -- 成功
-- 超出整数部分限制
INSERT INTO bank_account VALUES (1003, '王五', 100000000.00);
-- 错误:总位数超过10位(整数部分8位+小数2位=10位,100000000是9位整数)
-- 超出小数部分限制
UPDATE bank_account SET balance = 12345.678 WHERE account_id = 1001;
-- 错误:小数位3位 > 2位(自动四舍五入为12345.68)
特性 | decimal | float |
---|---|---|
精度保证 | 精确存储(无误差) | 近似存储(有误差) |
适用场景 | 财务计算、货币金额 | 科学测量、大范围值 |
计算速度 | 较慢(精确计算开销大) | 较快 |
存储空间 | 较大(每9位需4字节) | 固定4字节 |
数值范围 | 受M限制(最大10^65) | 极大(约±10^38) |
小数处理 | 精确舍入 | 二进制近似 |
decimal
decimal(19,4)
(兼容国际标准)
decimal(5,2)
(存储0.00~999.99%)
黄金法则:当需要精确计算时选择
decimal
,当可接受近似值时选择float
。在金融、电商、账务系统中,decimal
的精度保障远重于其性能开销。
通过 decimal
类型,MySQL 为开发者提供了符合银行级标准的数值存储方案。它的精确性特性使其成为处理货币金额、财务计算和任何需要完美精度的商业场景的首选工具。
以上就是我想要讲述的MySQL中关于数值类型的定义,各位目前想要掌握它们,我的建议是在后续我进行DML的时候,跟着我一起敲代码。那么就可以更快的去掌握这些知识,毕竟比起死记硬背,动用往往是记忆最好的方式,下面我要进行字符串类型的讲述了。
char类型相比数值类型,用法就比较简单了,下面先来看看它的语法。
char(L): 固定长度字符串,L是可以存储的长度,单位为字符,最大长度值可以为255
这个语法接受起来就比上面的float要简单很多,我们仅需知道,此时char括号里面的数字代表的事可以存储的字符的长度,记住,说的是字符的长度,而不是字节的长度,就比如,'你好'就代表两个字符,'A'代表一个字符等等,下面我就通过一个例子来告诉各位它的用法。
下面,我继续从student表里面添加一列,充当家庭住址(place),其用法如下(此时设计表的增的操作,我上篇文章已经介绍了,忘记的读者自行去看我上篇文章)。
alter table student add place char(20);
此时,即可看到表里新增的一列。
下面我往里面插入20个字符(测试阈值),可以看到插入是成功的。
但是当我插入21个字符的时候,系统就会报错了,这就可以看出MySQL对于数据范围控制的严谨性。
varchar(L): 可变长度字符串,L表示字符长度,最大长度65535个字节
varchar
也是一种字符串类型。你可能会问,既然已有 char
类型,为何还需要 varchar
?关键在于它们的存储机制不同。
如前所述,char
是固定长度的字符串。例如,当你定义一个长度为 20 个字符的 char
字段时,即使你只插入了一个字符的数据,数据库依然会分配完整的 20 个字符空间。
而 varchar
则是可变长度的字符串。在同样的场景下(定义长度为 20,但仅插入 1 个字符),varchar
类型只会分配实际所需的空间,即仅占用 1 个字符的空间。
因为它和char类型的字符串其实很像(只不过是一个静态一个动态),所以此时我就不写用法了(偷懒一下)。
此时,我们可以通过一张表格来看出这两个类型的区别。
从这张图可以看出这俩的区别,我刚才也说了,varchar是变长的字符串,所以它的大小是根据当时字符大小来决定的,而char类型是定长字符串,无论输入了多少个字符,只要在和合理的范围内,它们的大小是确定的。
常用的日期有如下三个:
我们先来简单的使用一下date函数,此时我们往student表里新插入一列,bir代表学生的出生日期。
alter table student add bir date;
往里面插入一个元素,这里我就拿我自己的出生日期作为要插入的元素,因为这里面设计到了DML的知识,所以各位先不用记住它的用法。
insert into student(bir) values('2005-2-17');
检查一下此时是否插入成功。
下面我们继续插入新的一列,此时就用enr来表示,代表着入学的年份。
alter table student add enr datetime;
往里面插入随机一个元素,记住用年月日时分秒来表示。
insert into student(enr) values('2023-9-3-12:32:12');
此时就代表插入成功,看一下student里面存放的元素。
由于其用法和datetime类似,这里我就不多介绍了(后续我可能重新补充一下)。
此时文章到这里就结束了,这篇文章写的比较赶,但也不能说是很赶,因为我前后大约四天才写完的,所以文章可能读起来不是那么流畅,这里我先说一声抱歉了,出现这样的原因是因为我这周是期末周,大多时间都是在‘预习’知识,信号和系统真的很痛苦,我是真的不太喜欢这门课,导致我学起来特别的难受,到现在我的脑子还是比较混乱的。本文其实还有集合类型没有讲述,但是由于我很少使用它,所以我就先不写了,后期我可能会补充一点。在最后的hike,祝各位同时处在期末周的大学生们取得一个好成绩,祝各位已经放假的大学生们暑假快乐,祝所有人身体健康,每天都快快乐乐的,我是忘梓,一个默默无闻的小博主,各位大佬们,我们下篇文章见啦!