MySQL表设计(三大范式 表的设计)

1.上讲约束复习:


1.NOT NULL 非空约束,被指定NOT NULL的列,值不允许为空(必填)

2. UNIQUE 唯一约束,这个列里的值在表中是唯一的,也就是说不能重复

3. PRIMARY KEY 主键约束,可以看做是NOT NULL和UNIQUE的组合可以用一个bigint类型列为表单独指定主键,同时也可以指定主键自增,用auto increment关键字自增操作时,会找到当前列中最大的值,然后在这个基础上加1(+1)

4.DEFAULT 默认约束,如果写入一行记录的时候,指定了默认约束的列,如果在写入数据时没有指定一个确定的值就会用默认值进行填充该字段的值


5.FOREIGN KEY 外键约束,一张表要与另一张表的主键或唯一键进行关键,说明表与表之间的关联关系

2.三大范式

1.范式

数据库的范式是⼀组规则。在设计关系数据库时,遵从不同的规范要求,设计出合理的关系型数 据库,这些不同的规范要求被称为不同的范式。

关系数据库有六种范式:第⼀范式(1NF)、第⼆范式(2NF)、第三范式(3NF)、巴斯-科德 范式(BCNF)、第四范式(4NF)和第五范式(5NF,⼜称完美范式),越⾼的范式数据库冗余越 ⼩。然⽽,普遍认为范式越⾼虽然对数据关系有更好的约束性,但也可能导致数据库IO更繁忙,因此 在实际应⽤中,数据库设计通常只需满⾜第三范式即可。

2.第一范式   确保每个字段的原子性

定义:
• 数据库表的每⼀列都是不可分割的原⼦数据项,⽽不能是集合,数组,对象等⾮原⼦数据。

• 在关系型数据库的设计中,满⾜第⼀范式是对关系模式的基本要求。不满⾜第⼀范式的数据库就不能被称为关系数据库

要求:

  • 每个字段只能包含一个值(没有重复组)。
  • 表中的每一行应当是唯一的,可以通过主键进行标识。

使用:

第一范式要求每个字段(列)只能有一个值,不能是多个值的集合。

不符合第一范式的设计:

假设我们一开始设计了一个学生表,课程 字段存储了多个课程:

插入数据时,可以看到 courses 列存储了多个课程:

我们可以看出这个设计存在问题,courses 列可以储存多个值,违反了第一范式。我们应该将每个课程单独存储。

符合第一范式的设计:

为了遵循第一范式,我们需要将课程数据拆成每个学生每门课程一行:

学生表:

课程表:

然后插入数据:

这样,每个课程都拆成了单独的一行,符合第一范式。

第二范式(2NF):消除部分依赖

定义:
满⾜第⼀范式的基础上,不存在⾮关键字段对任意候选键的部分函数依赖。存在于表中定义了复合 主键的情况下。

候选键:可以唯⼀标识⼀⾏数据的列或列的组合,可以从候选键中选⼀个或多个当做表的主键

要求:

  • 表必须符合第一范式(1NF)。
  • 所有非主键字段必须完全依赖于主键,而不是依赖于主键的一部分。
  • 部分依赖是指,当主键由多个字段组成时,某些非主键字段仅依赖于主键的其中一部分,而不是整个主键。
  • 问题:

    当我们使用复合主键时,如果某些列只依赖于主键的一部分而不是整个复合主键,那么这种依赖就叫做“部分依赖”,这违反了第二范式。

不符合第二范式的设计:

假设我们设计了一个订单表,其中 订单号商品ID 组成复合主键:

假设插入以下数据:

解释:

  • 主键:(order_id, product_id),这个复合主键的意思是每个订单(order_id)包含多个商品(product_id),每个商品的数量(quantity)将会是订单明细的一部分。
  • 然而,product_name 字段并不依赖于 order_id(订单号),它仅依赖于 product_id(商品ID)。也就是说,product_name 是与 product_id 紧密相关的,但不依赖于 order_id

具体来说:

  • 订单号 (order_id) 决定了订单的唯一性。
  • 商品ID (product_id) 决定了商品的唯一性。
  • 但商品的名字(product_name)只与商品ID (product_id) 相关,而与订单号 (order_id) 无关。

因此,product_name 并没有完全依赖于整个复合主键(order_idproduct_id),它只是部分依赖于 product_id。这就违反了第二范式的要求。

为什么这违反了第二范式?

根据第二范式的要求,所有非主键字段必须完全依赖于复合主键,而不能只依赖于主键的一部分。在我们的设计中,product_name 只依赖于 product_id,而不是完整的复合主键 (order_id, product_id)。因此,product_name 存在部分依赖,违反了第二范式。

符合第二范式的设计:

为了使表符合第二范式,我们需要消除部分依赖。具体来说,我们可以将 product_name 字段移到一个单独的表中,专门存储商品信息,这样 product_name 就会只依赖于 product_id,而不是依赖于复合主键 (order_id, product_id)

新的设计方案:
  1. 订单表 (orders):存储订单信息。

2.商品表 (products):存储商品信息,每个商品有一个 product_idproduct_name

3.订单明细表 (order_items):存储每个订单的商品信息。主键依然是 (order_id, product_id),但是商品信息不再在此表中存储,而是通过 product_id 关联到 products 表。

数据插入示例:

插入订单数据:

插入商品数据:

插入订单明细数据:

解释:
  • product_name 现在存储在 products 表中,且只依赖于 product_id。它不再依赖于复合主键 (order_id, product_id)
  • order_items 表只存储每个订单的商品和数量,不再包含商品名称,商品名称通过 product_id 关联到 products 表中。

通过这种设计:

  • product_name 不再存在部分依赖,它完全依赖于 product_id
  • order_items 表现在只存储与订单相关的信息,完全符合第二范式。

不满⾜第⼆范式时可能出现的问题

1. 数据冗余

学⽣的姓名、年龄、性别和课程的学分在每⾏记录中重复出现,造成了⼤量的数据冗余。

2. 更新异常

如果要调整MySQL的学分,那么就需要更新表中所有关于MySQL的记录,⼀旦执⾏中断导致某些 记录更新成功,某些数据更新失败,就会造成表中同⼀⻔课程出现不同学分的情况,出现数据不⼀致 问题。

3. 插⼊异常

⽬前这样的设计,成绩与每⼀⻔课和学⽣都有对应关系,也就是说只有学⽣参加选修课程考试取 得了成绩才能⽣成⼀条记录。当有⼀⻔新课还没有学⽣参加考试取得成绩之前,那么这⻔新课在数据 库中是不存在的,因为成绩为空时记录没有意义。

4. 删除异常

把毕业学⽣的考试数据全都删除,此时课程和学分的信息也会被删除掉,有可能导致⼀段时间 内,数据库⾥没有某⻔课程和学分的信息。

5.解决方案

将依赖于主键一部分的字段(如 product_name)移动到另一个独立的表中,确保每个非主键字段都完全依赖于整个复合主键。

第三范式(3NF):避免不必要的间接依赖

什么是第三范式?
第三范式要求数据表符合第二范式,并且消除传递依赖。传递依赖是指:如果字段A依赖于字段B,字段B又依赖于字段C,那么字段A间接依赖于字段C。为了避免这种情况,我们需要确保每个字段只直接依赖于主键。

第三范式(3NF)的要求:

  1. 表必须符合第二范式(2NF),即消除部分依赖。
  2. 消除传递依赖:如果一个非主键字段依赖于另一个非主键字段,那么这就是传递依赖。第三范式要求非主键字段只能直接依赖于主键,而不能间接依赖于主键。

什么是传递依赖?

假设有一个表,表中的字段依赖于主键的某些其他字段,而这些字段并不直接依赖于主键本身,而是通过其他非主键字段间接依赖。这种依赖称为传递依赖

不符合第三范式的设计示例:

假设我们设计了一个员工表employees),包含 部门编号部门名称 两个字段。

插入数据:

为什么这个设计违反了第三范式?

  • 传递依赖的存在
    • employee_id 是主键,它唯一标识每一行。
    • department_id 依赖于 employee_id,而 department_name 依赖于 department_id。因此,department_name 通过 department_id 间接依赖于主键 employee_id
    • 问题department_name 不应该依赖于 department_id,而是应该依赖于 department_id 的表。我们应该消除这种间接依赖,确保所有的非主键字段只直接依赖于主键。

这种情况下,department_name 是通过 department_id 间接依赖于主键 employee_id,这就是传递依赖。根据第三范式,非主键字段(department_name)应当直接依赖于主键(employee_id),而不是依赖于其他非主键字段。

符合第三范式的设计:

为了消除传递依赖,我们可以将 department_name 字段移动到一个独立的表中,专门存储部门信息。这样,department_name 就会直接依赖于 department_id,而不会通过 employee_id 间接依赖。

新的设计方案:
  1. 员工表 (employees):只存储与员工相关的信息,去掉 department_name 字段。

2.部门表 (departments):存储部门信息,每个部门有 department_iddepartment_name

数据插入示例:

插入部门数据:

插入员工数据:

解释:
  • employees 表中,department_id 作为外键引用了 departments 表中的 department_id,不再存储 department_name
  • departments 表专门存储了部门信息,department_name 直接依赖于 department_id,而 department_idemployees 表中作为外键,依赖于 employee_id

通过这种方式,department_name 不再依赖于 employee_id,而是直接依赖于 department_id,从而消除了传递依赖,符合第三范式。

总结:

  • 传递依赖:在原设计中,department_name 通过 department_id 间接依赖于主键 employee_id,这就是传递依赖。
  • 符合第三范式的设计:将 department_name 移到独立的部门表中,department_name 直接依赖于 department_id,而 employee_id 只与员工信息相关,消除了传递依赖,符合第三范式。

通过这样的调整,表结构更加简洁,避免了数据冗余和更新异常,提高了数据库的一致性和完整性。

3. 设计过程

需求分析阶段

在开始设计数据表之前,首先需要进行详细的需求分析,这一阶段的关键是了解应用的业务需求和系统的功能。通过与客户、开发团队、产品经理等的沟通,收集以下信息:

  • 业务流程:了解业务的流程和操作步骤,确定哪些数据需要存储。
  • 数据类型:识别哪些数据需要存储,并明确所有数据的属性。
  • 数据关系:明确不同数据之间的关系,是否需要多表关联,主键、外键如何设计。
  • 查询需求:确定系统将如何查询、筛选和统计数据,这有助于升级优化索引和查询性能。
  • 数据一致性:了解数据的完整性要求,确保数据的准确性和一致性。

2.定义实体和属性

在需求分析之后,接下来就是**定义实体(表)属性(字段)**的阶段。这一步的目标是确定存储哪些数据及其具体的结构。你可以通过以下步骤完成这个阶段:

实体被识别

实体是需要存储在数据库中的业务对象。例如,在一个电商系统中,常见的实体可能包括:

  • 用户(用户)
  • 订单(命令)
  • 商品(产品)
  • 支付(支付)
属性定义

每个实体都有自己的属性,这些属性决定了表中的列。比如,用户实体可能有以下属性:

  • 用户ID(user_id
  • 用户名(username
  • 密码(password
  • 电子邮箱(email
  • 注册时间(registration_date

3.设计结构

根据后续实体和属性的定义,开始设计数据库表结构。包括以下几个关键点:

确定主键(Primary Key)

每个表格必须有一个主键,主键用于唯一标识一行数据,保证数据的唯一性。主键的选择原则:

  • 唯一性:主键值必须唯一,不能重复。
  • 不可为空:主键字段不能为空(NULL)。
  • 稳定性:主键值应稳定,易于改变。

例如,用户表的主键可以是user_id

选择项

为每个存储字段的数据选择合适的数据类型。例如:

  • 对于字符串数据使用VARCHARTEXT类型。
  • 对于整数数据使用INTBIGINT类型。
  • 对于时间日期数据使用DATETIMETIMESTAMP类型。
定义约束
  • 唯一约束UNIQUE):确保字段中的值是唯一的,例如用户名和电子邮件地址。
  • 外键约束FOREIGN KEY):定义表与表之间的关联关系,例如订单表中的user_id外键,指向用户表user_id
  • 非空约束NOT NULL):确保字段不能为空。
  • 默认值DEFAULT):字段没有值时使用的默认值。
设计索引(Index)

索引是为了加速查询而创建的数据结构。可以在用于经常查询条件的字段(如user_idorder_date)上创建索引,以提高查询性能。注意:

  • 索引可以加速查询,但同时也会影响插入、更新操作的性能。
  • 不要在每个字段上都创建索引,应该根据实际的查询需求来优化索引。

4. 实体-关系图

实体-关系图(Entity-RelationshipDiagram)简称E-R图,也称作实体联系模型、实体关系模型,是 ⼀种⽤于描述数据模型的概念图,主要⽤于数据库设计阶段。

 E-R图的基本组成 E-R图包含了以下三种基本成分:

• 实体:即数据对象,⽤矩形框表⽰,⽐如⽤⼾、学⽣、班级等。

• 属性:实体的特性,⽤椭圆形或圆⻆矩形表⽰,如学⽣的姓名、年龄等。

• 关系:实体之间的联系,⽤菱形框表⽰,并标明关系的类型,并⽤直线将相关实体与关系连接起 来。

关系的类型:

1. ⼀对⼀关系(1:1)

• ⼀个⽤⼾实体包含的属性有:⽤⼾昵称,真实姓名,⼿机号,邮箱地址,性别,学校

• ⼀个账⼾实体包含的属性有:登录⽤⼾名,密码

• ⽤⼾实体与账⼾实体是⼀对⼀的关系,⽤E-R图表⽰如下:

2 ⼀对多关系(1:N)

• ⼀个学⽣实体包含的属性有:真实姓名,学号,年龄,性别,⼊学时间

• ⼀个班级实体包含的属性有:班级名,学⽣⼈数

• ⼀个班级中有多个学⽣,所以班级实体与学⽣实体是⼀对多的关系,反过来说学⽣实体与班级实体 是多对⼀着么,⽤E-R图表⽰如下:

3 多对多关系(M:N)

• ⼀个学⽣实体包含的属性有:真实姓名,学号,年龄,性别,⼊学时间

• ⼀个课程实体包含的属性有:课程名

• ⼀个学⽣可以选修改多⻔课程,⼀⻔课程也可以被多名学⽣选修改,所以学⽣与课程之间是多对多 关系,⽤E-R图表⽰如下:

• 对于多对多关系,可以使⽤中间表进⾏记录,⽐如⼀个学⽣参加了某⼀⻔课程的考试得到了相应的 成绩,⽤E-R图表⽰如下:

5.数据规范化

数据规范化是指通过剔除数据表,保证数据表的结构简洁、稳定性。规范化过程分为不同的范式,通常包括以下几个阶段:

  • 第一范式(1NF):确保表中的每一列都是原子性的,即每一列只能包含一个值。
  • 第二范式(2NF):确保每个非主键字段完全依赖于主键,消除部分依赖。
  • 第三范式(3NF):消除供货依赖,确保每个非主键字段只直接依赖于主键。

6.性能。

在完成基本的表结构设计后,考虑到数据库的查询性能和扩展性,进行一些优化:

索引优化
  • 对常用查询条件字段(如user_idorder_id)建立索引。
  • 对涉及范围查询(如时间区间查询)的字段建立合适的索引。
  • 避免对小表创建过多的索引,因为它们会增加数据库的写入操作成本。
分表

如果表的数据量非常大,可能需要进行分表(水平分割)或分区(垂直分割)。例如,可以将订单表按日期分区,或者将用户表按地区分割表。

7.安全性和备份

  • 数据安全性:确保对敏感数据(如密码)进行加密存储。可以使用加密算法存储密码,避免明文存储。
  • 数据备份:设计数据库策略备份,定期备份数据库以防止数据丢失。

8.实现和测试

最后,将设计好的数据表转化为SQL语句,执行数据库创建操作。在实现过程中,确保:

  • 测试数据的权限:确保表设计不违反数据约束、数据依赖等规则。
  • 查询性能测试:测试常用的查询是否快速,特别是对于大数据量的查询。

总结:

在数据库设计的历程中,我们最大的架构师,构建了一座数据的大厦!从需求分析到表格结构设计,每一步都充满了挑战和创意。通过仔细梳理业务需求,我们为数据定义了语音的“身份”,让每个表都成为数据的家,确保他们井然有序且不显现。

我们不仅要保证数据的一致性,还要让它们始高效性,让查询速度

而为了应对未来的增长,我们更通过索引优化和**分区设计分区设计,让数据库

设计好一个数据库表,意味着你为数据架建立了一个坚固又高效的桥梁。通过表与表之间紧密的关系,每一条数据都能顺利流动,应用系统也能流畅运行。最后,我们还要时刻关注安全性和备份

总的来说,数据库设计不仅仅是技术工作,它是一门思维的艺术!每一个设计决策都决定了系统的未来,它是数据和业务需求聚合的完美融合。希望数据库设计的旅程,能够让你愉快地掌握如何设计出、安全、易于维护的高效数据库系统

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/909896.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

基于SpringBoot的免税商品优选购物商城的设计与实现

一、项目背景 从古至今,通过书本获取知识信息的方式完全被互联网络信息化,但是免税商品优选购物商城,对于购物商城工作来说,仍然是一项非常重要的工作。尤其是免税商品优选购物商城,传统人工记录模式已不符合当前社会…

RabbitMQ 存储机制

一、消息存储机制 不管是持久化的消息还是非持久化的消息都可以被写入到磁盘。持久化的消息在到达队列时就被写入到磁盘,非持久化的消息一般只保存在内存中,在内存吃紧的时候会被换入到磁盘中,以节省内存空间。这两种类型的消息的落盘处理都…

Kafka自动生产消息软件(自动化测试Kafka)

点击下载《Kafka服务端(含Zookeeper)一键自启软件》 点击下载《kafka客户端生产者消费者kafka可视化工具(可生产和消费消息)》 点击下载《Kafka自动生产消息软件》 1. 前言 在软件开发过程中,Kafka常被用作消息队列来处理特定的业务功能。为…

C#应用随系统启动 - 开源研究系列文章

上次写过一个随系统启动的例子,不过那个是写到注册表中的,自从更新Windows操作系统后就不好使了,所以就换了个方式,只是将应用的快捷方式添加到操作系统的启动目录里,这样随系统启动。 1、 项目目录; 2、 源…

大语言模型在交通领域的应用分析

大语言模型在交通领域的研究进展 前言: 大语言模型(Large Language Models, LLMs)如 GPT (Generative Pre-trained Transformer) 系列,BERT (Bidirectional Encoder Representations from Transformers) 和其他基于 Transformer …

快速删除iPhone照片:释放你的空间,加速你的手机

随着时间的推移,我们的iPhone往往会积累下大量的照片,这不仅占用了大量的存储空间,还可能影响手机的性能。如果你正寻找一种快速、高效的方法快速删除iPhone照片,以下的策略将会大有帮助。此外,本文还将介绍如何利用Cl…

matlab 质心重合法实现点云配准

目录 一、算法原理1、原理概述2、参考文献二、代码实现三、结果展示1、初始位置2、配准结果本文由CSDN点云侠原创,原文链接,首发于:2024年11月5日。 一、算法原理 1、原理概述 质心重合法是将源点云 P P P

MySQL数据库中的视图

视图 ​ 本篇将开始介绍有关数据库中视图的相关知识点,其中主要包含视图的基本使用,视图规则和限制。 ​ 视图是一个虚拟表,其内容由查询定义。同真实的表一样,视图包含一系列带有名称的列和行数据,视图的数据变化会…

软件测试基础:单元测试与集成测试

单元测试的重要性 单元测试是软件开发过程中的必要步骤。它通过针对软件的最小可测试单元进行测试,可以及早发现代码中的逻辑错误和缺陷。根据统计数据显示,单元测试可以在软件开发初期就发现约70%的错误,从而减少了后期修改的成本和时间消耗…

昆仑通态触摸屏-如何完成几个窗口的切换

一、启动窗口 想要哪一个窗口是启动时第一个显示的,就把谁设置为启动窗口就可以。 二、公共窗口 给一个窗口命名为公共窗口 然后选择一个窗口,将他的公共窗口设置为我们刚才命名的那个窗口 三、页面切换 页面切换,是通过在公共窗口内设置按…

修改elementUI等UI组件样式的5种方法总结,哪些情况需要使用/deep/, :deep()等方式来穿透方法大全

文章目录 方法 1:全局修改样式示例:修改 `ElMessage` 的背景色和字体颜色方法 2:修改特定类型的 `ElMessage` 样式-全局-不需要穿透示例:修改 `ElMessage` 成功类型的样式方法 3:通过 Scoped CSS 在组件内部修改-局部-不需要穿透方法 4:使用 JavaScript 动态修改样式-不需…

SpringBoot中使用SpringTask实现定时任务

SpringBoot默认在无任何第三方依赖的情况下使用spring-context模块下提供的定时任务工具SpringTask。我们只需要使用EnableScheduling注解就可以开启相关的定时任务功能。 定义一个SpringBean,然后定义具体的定时任务逻辑方法并使用Scheduled注解标记该方法即可。…

CTF中的phar反序列化 [SWPU 2018]SimplePHP

以[SWPU 2018]SimplePHP 这道题为例 页面可以查看文件和上传文件 点击查看文件,发现url变成/file.php?file 猜测可能存在文件包含,可以读取文件 尝试读取index.php文件 回显了源码 再读取base.php 只看最后有信息的代码: <!--flag is in f1ag.php--> 提示flag在f1…

车载通信架构 --- PNC、UB与信号的关系

我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 所有人的看法和评价都是暂时的,只有自己的经历是伴随一生的,几乎所有的担忧和畏惧,都是来源于自己的想象,只有你真的去做了,才会发现有多快乐。…

C++进阶-->红黑树的实现

1、红黑树的概念 红黑树是一棵二叉搜索树&#xff0c;他和前面AVL树不同的是红黑树不是通过平衡因子来保证树的平衡&#xff0c;而是在树结点的处加多了个记录颜色的变量&#xff0c;这个变量可以是红色或者黑色。通过对任何一条从根到叶子的路径上各个结点的颜色进行约束&…

微信公众号绑定设计-WeChat public platform bing and send message

一 WeChat bind ui 二、message style 三、 consume style 四、send log 五、temp setting

Linux多线程(个人笔记)

Linux多线程 1.Linux线程概念1.1线程的优点1.2线程的缺点 2.Linux线程VS进程3.Linux线程控制3.1创建线程3.2线程tid及进程地址空间布局3.3线程终止3.4线程等待 4.分离线程5.线程互斥5.1互斥锁mutex5.2互斥锁接口5.3互斥锁实现原理5.4可重入VS线程安全 6.线程同步6.1条件变量6.2…

Java项目实战II基于Spring Boot的药店管理系统的设计与实现(开发文档+数据库+源码)

目录 一、前言 二、技术介绍 三、系统实现 四、文档参考 五、核心代码 六、源码获取 全栈码农以及毕业设计实战开发&#xff0c;CSDN平台Java领域新星创作者&#xff0c;专注于大学生项目实战开发、讲解和毕业答疑辅导。 一、前言 随着医疗行业的快速发展和人们对健康需…

LDO电路分析

一、LDO概述 在电压转换电路中&#xff0c;LDO和DC-DC电路是最常用的两种方式&#xff0c;本篇主要介绍LDO相关内容。 LDO是线性电源的一种&#xff0c;它可以实现电源电压的转换&#xff0c;不过主要用在降压领域。它的全称是Low Dropout Regulaor&#xff0c;就是低压差线性…

VirtualBox虚拟机扩容详解

VirtualBox虚拟机扩容详解 virtualbox 扩容找到虚拟机需要扩容的磁盘更改虚拟磁盘的大小 逻辑卷扩容1. 扩展物理卷2. 扩展逻辑卷3. 扩展文件系统 Ubuntu系统安转 minikube 集群后&#xff0c;提示文件系统要炸了&#xff0c;效果如下&#xff1a;可以明显看到 /dev/mapper/ubu…