当前位置: 首页 > news >正文

掌握 MySQL 的基石:全面解读数据类型及其影响

前言

        上篇文章小编讲述了关于MySQL表的DDL操作,在那里我多次使用了MySQL的数据类型,但是我并没有去讲述MySQL的数据类型,想必各位读者已经很好奇MySQL的数据类型都有什么了,今天这篇文章我将会详细的去讲述MySQL的数据类型,希望可以为各位解惑。

1.数据类型以及分类

        在详细说明每个数据类型之间,我先来让各位看一看MySQL中有几种数据类型以及它们的分类(只截取了比较重要的一部分,还有一些我并没有展示出来,各位读者感兴趣可以去官方网站自行学习)。

        上面的类型有很多种,不过很多我们在学C语言的时候就已经感到很熟悉了,就比如数值类型中的int类型,它就是我们在C语言学习的整型,这点MySQL和C语言还是一样的,当然MySQL和C语言还是有差异的地方的,就比如文本类型的中的char,在C语言中,它代表的是字符类型,也就是'A'、'B'等等的字符;而它在MySQL代表的事一个固定长度的字符串,各位千万不要把它的定义和C语言的混为一谈。下面我将从数值类型、文本。二进制类型。时间日类类型以及string类型这几个方面,详细讲述MySQL的数据类型以及它和编程语言的异同,帮各位避开这些认知陷阱。

2.数值类型

        上表就是我想要讲述的数值类型,此时我先简单的带着各位看下这个表,这个表大多数的都是和整型int相关的,之所以放到一起是因为我认为它们是有相似性的,当我讲述完其中几个以后,剩下的类型各位就可以自己去领悟了(绝对不是因为我偷懒),下面我来分别讲述一下这几种类型。

2.1.tinyint类型

        通过上表,我们可以简单的知道它所代表的范围是-128到127,因为它是占据一个字节,一个字节是八个比特位,所以它可以表示2^8也就是256个不同的值(从00000000到11111111);在计算机用补码表示有符号整数时,最高位为0表示正数(0到127),最高位为1表示负数(-1到-128),其中 10000000 这个特殊编码被定义为 -128,因此整体范围就是 -128 到 127。因此它的范围就是-128到127,可能有些读者好奇它的范围真的卡的那么严吗?不要急,下面我简单的进行范围的测试(里面涉及到表的DML的知识,这是我下一篇文章要讲述的,各位读者可以先期待着)。

1.范围检测

        此时我简单的建立一个表,这个表的名字是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)的核心机制与此完全相同,区别仅在于它们能容纳的范围大小不同。既然原理一致,我们就不再逐一赘述。接下来,让我们把目光转向另一种重要的数据类型——小数类型

2.2.小数类型

1.float类型

语法:

float[(m, d)] [unsigned] : M指定显示长度,d指定小数位数,占用空间4个字节 

        与整型不同,float类型在定义时需要指定两个参数,语法为 float(M, D)。下面我来详细解释这两个参数的含义和使用规则:

参数解析
  1. M (总精度/显示宽度):代表该浮点数总共可以显示的最大数字位数(包括整数部分和小数部分的所有数字字符,不包括小数点本身和符号位)。

    • 例如:128.1 包含数字 1,2,8,1 → 总共 4 位数字

    • 12.81 包含数字 1,2,8,1 → 总共 4 位数字

  2. D (小数位数/标度):代表该浮点数小数点后允许的最大位数

    • 例如:128.1 的小数点后有 1 位数字 (1)

    • 12.81 的小数点后有 2 位数字 (81)

关键特性
  • MD 定义的是上限值[敲重点]:实际存储的数字位数可以少于 M,小数位数可以少于 D,但不能超过

  • float 存储的是近似值而非精确值(这一点与整型完全不同)

  • 数值范围极大(约 ±10^38),但精度有限(约7位有效数字)

实例演示

        下面我通过一个建表实例,展示 float 类型的使用规则:

1. 创建测试表
-- 创建包含float(4,2)类型的测试表
CREATE TABLE product (name VARCHAR(20),  -- 产品名称price FLOAT(4,2)   -- 价格(总位数不超过4,小数位不超过2)
);
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位
3. 插入非法数据(验证限制)
-- 超出总位数限制(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位小数,但总位数超限)
4. 查询验证
SELECT * FROM product;

        执行结果应显示:

+-----------+-------+
| name      | price |
+-----------+-------+
| 铅笔      | 12.34 |
| 橡皮      |  8.50 | -- 自动补零显示
| 笔记本    | 99.99 |
+-----------+-------+
重要注意事项
  1. 精度陷阱float 存储的是近似值,对精度要求高的场景(如金融计算)应使用 decimal 类型

    -- 精度问题示例
    INSERT INTO product VALUES ('计算器', 1.0 / 3.0); -- 存储为0.3333333432674408
  2. 参数可选性:可以不指定 (M,D),此时使用系统默认精度

    CREATE TABLE temp (value FLOAT); -- 不指定参数
  3. 显示补充:当实际小数位不足时,查询结果会自动补零显示(如 8.5 显示为 8.50

        通过以上实例,各位读者可以清晰看到:float(4,2) 可以存储 12.34(刚好满位)、8.5(位数不足)和 99.99(边界值),但拒绝 100.00(总位数超限)和 12.345(小数位超限)。这种灵活的位数控制使 float 成为处理科学计算和大范围数值的理想选择,但切记它的近似特性可能带来精度问题!

2.decimal

        在金融计算、货币交易等需要绝对精度的场景中,decimal 类型是 MySQL 中最值得信赖的数据类型。与 float 的近似存储不同,decimal固定精度存储数值,确保计算结果完全精确,避免浮点数常见的舍入误差问题。

核心特性解析
  1. 精确存储机制

    • 将数值拆分为整数部分小数部分分别存储

    • 采用定点数表示法,而非浮点数的科学计数法

    • 完全避免二进制浮点数的精度损失问题

  2. 参数定义语法

    decimal(M, D)
    • M (总精度):总位数(整数部分+小数部分),范围 1-65

    • D (小数位数):小数点后的位数,范围 0-30 且 D ≤ M

    • 示例decimal(5,2) 可存储 123.45(5位总数,2位小数)

  3. 存储空间优化

    • 每9位数字占用4字节

    • 存储空间 = 整数部分空间 + 小数部分空间

    • 示例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 vs float 关键对比
特性decimalfloat
精度保证精确存储(无误差)近似存储(有误差)
适用场景财务计算、货币金额科学测量、大范围值
计算速度较慢(精确计算开销大)较快
存储空间较大(每9位需4字节)固定4字节
数值范围受M限制(最大10^65)极大(约±10^38)
小数处理精确舍入二进制近似
重要注意事项
  1. 四舍五入规则

    -- 显示指定精度时的自动舍入
    INSERT INTO bank_account VALUES (1004, '赵六', 123.456); 
    -- 实际存储:123.46(小数部分自动四舍五入到2位)
  2. 默认精度设置

    -- 不指定参数时使用默认精度
    CREATE TABLE tax_records (amount DECIMAL  -- 等效于decimal(10,0)
    );
  3. 零值处理

    -- 小数位不足时自动补零
    INSERT INTO bank_account VALUES (1005, '钱七', 500.5);
    SELECT balance FROM bank_account WHERE account_id = 1005;
    -- 显示:500.50
  4. 计算精度扩展

    -- 计算过程中会保留最大精度
    SELECT balance * 1.123456789 FROM bank_account;
    -- 结果将包含更多小数位
最佳实践建议
  1. 财务系统必选:所有货币金额、税率计算必须使用 decimal

  2. 合理设置精度

    • 货币:decimal(19,4)(兼容国际标准)

    • 百分比:decimal(5,2)(存储0.00~999.99%)

    • 科学测量:根据仪器精度确定

  3. 警惕隐式转换

    -- 混合类型计算可能导致精度丢失
    SELECT balance + 123.456 FROM bank_account; -- 结果会被截断
  4. 性能权衡:高并发系统需评估精确计算带来的性能开销

黄金法则:当需要精确计算时选择 decimal,当可接受近似值时选择 float。在金融、电商、账务系统中,decimal 的精度保障远重于其性能开销。

        通过 decimal 类型,MySQL 为开发者提供了符合银行级标准的数值存储方案。它的精确性特性使其成为处理货币金额、财务计算和任何需要完美精度的商业场景的首选工具。

        以上就是我想要讲述的MySQL中关于数值类型的定义,各位目前想要掌握它们,我的建议是在后续我进行DML的时候,跟着我一起敲代码。那么就可以更快的去掌握这些知识,毕竟比起死记硬背,动用往往是记忆最好的方式,下面我要进行字符串类型的讲述了。

3.字符串类型

3.1.char类型

1.语法

        char类型相比数值类型,用法就比较简单了,下面先来看看它的语法。

char(L): 固定长度字符串,L是可以存储的长度,单位为字符,最大长度值可以为255

        这个语法接受起来就比上面的float要简单很多,我们仅需知道,此时char括号里面的数字代表的事可以存储的字符的长度,记住,说的是字符的长度,而不是字节的长度,就比如,'你好'就代表两个字符,'A'代表一个字符等等,下面我就通过一个例子来告诉各位它的用法。

2.用法

        下面,我继续从student表里面添加一列,充当家庭住址(place),其用法如下(此时设计表的增的操作,我上篇文章已经介绍了,忘记的读者自行去看我上篇文章)。

alter table student add place char(20);

        此时,即可看到表里新增的一列。

        下面我往里面插入20个字符(测试阈值),可以看到插入是成功的。

        但是当我插入21个字符的时候,系统就会报错了,这就可以看出MySQL对于数据范围控制的严谨性。

3.2.varchar类型

1.语法
varchar(L): 可变长度字符串,L表示字符长度,最大长度65535个字节

   varchar 也是一种字符串类型。你可能会问,既然已有 char 类型,为何还需要 varchar?关键在于它们的存储机制不同。

        如前所述,char固定长度的字符串。例如,当你定义一个长度为 20 个字符的 char 字段时,即使你只插入了一个字符的数据,数据库依然会分配完整的 20 个字符空间

        而 varchar 则是可变长度的字符串。在同样的场景下(定义长度为 20,但仅插入 1 个字符),varchar 类型只会分配实际所需的空间,即仅占用 1 个字符的空间。

2.用法

        因为它和char类型的字符串其实很像(只不过是一个静态一个动态),所以此时我就不写用法了(偷懒一下)。

3.3.char类型和varchar类型的比较

1.比较

        此时,我们可以通过一张表格来看出这两个类型的区别。

        从这张图可以看出这俩的区别,我刚才也说了,varchar是变长的字符串,所以它的大小是根据当时字符大小来决定的,而char类型是定长字符串,无论输入了多少个字符,只要在和合理的范围内,它们的大小是确定的。

2.如何选择这两种类型
  • 如果数据确定长度都一样,就使用定长(char),比如:身份证,手机号,md5 【但是我一般也是用varchar】。

  • 如果数据长度有变化,就使用变长(varchar), 比如:名字,地址,但是你要保证最长的能存的进去 。

  • 定长的磁盘空间比较浪费,但是效率高。

  • 变长的磁盘空间比较节省,但是效率低。

  • 定长的意义是,直接开辟好对应的空间

  • 变长的意义是,在不超过自定义范围的情况下,用多少,开辟多少。

4.日期和时间类型

1.相关函数

        常用的日期有如下三个:

  • date:日期。‘yyyy-mm-dd’,占用三个字节。

  • datetime:时间日期格式,‘yyyy-mm-dd HH:ii:ss’表示范围从1000到9999,占用八个字节。

  • timestamp:时间戳(比较常见的概念,之前我在C语言也使用过它),从1970年开始的yyyy-mm-dd HH:ii:ss格式和datetime完全一致,占用四个字节。

2.使用方法

1.date函数

        我们先来简单的使用一下date函数,此时我们往student表里新插入一列,bir代表学生的出生日期。

alter table student add bir date;

        往里面插入一个元素,这里我就拿我自己的出生日期作为要插入的元素,因为这里面设计到了DML的知识,所以各位先不用记住它的用法。

insert into student(bir) values('2005-2-17');

        检查一下此时是否插入成功。

2.datetime

        下面我们继续插入新的一列,此时就用enr来表示,代表着入学的年份。

alter table student add enr datetime;

        往里面插入随机一个元素,记住用年月日时分秒来表示。

insert into student(enr) values('2023-9-3-12:32:12');

        此时就代表插入成功,看一下student里面存放的元素。

3.timestamp

        由于其用法和datetime类似,这里我就不多介绍了(后续我可能重新补充一下)。

5.小结

        此时文章到这里就结束了,这篇文章写的比较赶,但也不能说是很赶,因为我前后大约四天才写完的,所以文章可能读起来不是那么流畅,这里我先说一声抱歉了,出现这样的原因是因为我这周是期末周,大多时间都是在‘预习’知识,信号和系统真的很痛苦,我是真的不太喜欢这门课,导致我学起来特别的难受,到现在我的脑子还是比较混乱的。本文其实还有集合类型没有讲述,但是由于我很少使用它,所以我就先不写了,后期我可能会补充一点。在最后的hike,祝各位同时处在期末周的大学生们取得一个好成绩,祝各位已经放假的大学生们暑假快乐,祝所有人身体健康,每天都快快乐乐的,我是忘梓,一个默默无闻的小博主,各位大佬们,我们下篇文章见啦!

http://www.lryc.cn/news/576335.html

相关文章:

  • ReasonGraph 大模型推理过程可视化开源工具使用探索,大模型幻觉可视化研究
  • zookeeper Curator(1):认识zookeeper和操作命令
  • [论文阅读] 软件工程 | 微前端在电商领域的实践:一项案例研究的深度解析
  • React 第六十六节Router中 StaticRouter使用详解及注意事项
  • 前端React和Vue框架的区别
  • 深入理解C#委托操作:添加、移除与调用全解析
  • 网络 : 传输层【UDP协议】
  • Linux-读者写者问题
  • STM32F103C8T6参数说明
  • Android4的InputReader
  • 一款支持多日志器、多级别、多落地方式的同异步日志系统
  • 搭建Flink分布式集群
  • 零知开源——基于STM32F407VET6零知增强板的四路独立计时器
  • 配置阿里云OSS实现https访问
  • 解决flash-attn安装报错的问题
  • Java-对象的字符串表示
  • Day45 Tensorboard使用介绍
  • 计算机操作系统(十七)内存管理
  • 关于上位机的热更新
  • 暑假复习篇之运算与逻辑
  • C#数据流处理:深入解析System.IO.Pipelines的奥秘
  • 数据结构与算法 --- 双向链表
  • 鸿蒙 Scroll 组件深度解析:丝滑滚动交互全场景实现
  • Python 数据分析与可视化 Day 10 - 数据合并与连接
  • 华为云Flexus+DeepSeek征文|基于Dify构建文本/图像/视频生成工作流
  • C++虚函数详解:动态绑定机制深度解析
  • 创客匠人视角:创始人 IP 打造为何成为知识变现的核心竞争力
  • 如何在FastAPI中打造坚不可摧的Web安全防线?
  • 【C++】简单学——类和对象(下)
  • 从 AJAX 到 axios:前端与服务器通信实战指南