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

MySQL:数据库设计

目录

一、范式

二、第一范式

二、第二范式

三、第三范式

 四、设计

(1)一对一关系

(2)一对多关系

(3)多对多关系


一、范式

  数据库的范式是一种规则(规范),如果我们想要设计出合理的关系型数据库,我们就要遵守这些不同的规范,而这些不同的规范要求又被称之为范式。

  在我们的关系型数据库中有着六种范式:第一范式(1NF)、第二范式(2NF)、第三范(3NF)、巴斯-科德范式(BCNF)、第四范式(4NF)、第五范式(5NF,又称完美范式)。

  在这些不同的范式中我们认为越高的范式,数据库的冗余就越小,因此普遍认为范式越高对数据之间的关系有着更好的约束性,但是这种更高的范式也可能会导致我们数据库的IO更加繁忙,因此在我们的实际开发中,我们的数据库设计只需要满足第三范式即可

二、第一范式

定义:数据库表中的每一列都是不可分割的原子数据项,它们不能是集合,数组 ,对象等非原子数据。

注意:在关系型数据库的设计中,满足第一范式是对关系模式的基本要求。不满足第一范式的数据库就不能被称为关系数据库。

  如果我们单看完定义,我们可能不太了解什么是不可分割的原子项。我们接下来可以举一个简单的例子,我们设计一张学生表,在这个学生表中,存有我们的学生的个人信息和学校信息。

  我们设计出了这样的一个学生表,我们观察这个学生表的每一个列,我们可以发现,在我们的学校这一列,它其实是一个对象,是可以继续进行拆分的,我们可以将他拆分为:学校名,学校地址,学校电话,邮箱等等这些项,因此在这种还存在可以继续往下拆分的列时,我们称这个学生表是不满足第一范式的。

  那么,如果我们想要让我们这张学生表是满足第一范式的话,我们该怎么做呢,其实很简单,我们只需要将我们的学校列用拆分好的列进行替代即可。

  此时这样的一张新的学生表就是满足我们的第一范式了,同时我们发现我们此时的这张表的所有列都可以用基本数据类型进行表示,那么我们就可以认为,在我们的关系型数据库中如果我们的每一个列都可以用基本数据类型进行表示,那么我们就说他是天然满足第一范式的。

二、第二范式

定义:在满足第一范式的基础上,不存在非关键字段对任意候选键的部分函数依赖。如果我们的表中在定义了复合主键的情况下,存在部分函数依赖,我们就说它不满足第二范式。

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

  根据我们的定义来看,我们可能并不了解,我们其实可以对这个定义进行一个简化,那就是:在满足第一范式(1NF)的情况下,表中的每一个非主键字段都是完全函数依赖于主键字段的。

  当然,在这里可能有有所迷惑什么是完全函数依赖,我们接下来可以举一个例子来解释,我们设计一张成绩表,在这张表中存入我们的学生信息,学生课程,和学生所获课程学分和成绩。在这张表中我们将学号+课程名定义成复合主键

  但是在这张表中我们其实可以发现,我们学生信息(学生信息中除主键外的字段)是靠我们的学号这个字段来标识的,而我们的课程信息是靠课程名这个字段标识的,我们的成绩是靠这个两个字段标识的。 在这种非主键字段,不是全部依赖一个整个主键字段而是依赖主键中部分列的情况,我们就说他存在部分函数依赖,因此它是不满足第二范式的。

  并且在这种不满足部分函数依赖的情况下,它会导致许多的问题,而这些问题也就是我们为什么要引入范式的原因。

不满足第二范式可能会出现的问题,我们还是以上面设计的这张学生表来说明问题。

1、数据冗余

  在上面这张表中,我们其实可以看到学生的信息在每一行中会重复出现,例如第一行和第四行的学生信息。

2、更新异常

  例如如果我们要去调整Java的学分,那么我们就要更新表中所有Java的学分,但是如果在更新的过程中出现中断,导致一些数据更新成功,另一些数据更新失败,那么这样就会导致同一个Java学科会出现不同的学分,这就是我们的更新异常。

3、插入异常

如果我们想要只插入学生的学号,姓名,性别和年龄,而不插入课程名,此时就会出现插入异常,因为我们定义的主键是学号+课程名的复合主键,我们还需要添加我们的课程名

4、删除异常

当此时这个学生已经毕业了,那么我们留着他的成绩肯是没有用的,所有我们就要将他他的信息和成绩删除,但是如果我们要进行删除,我们同时也需要将课程和学分一并删除才能成功,这样就会导致了我们的数据库中的课程和学分会消失。

  那么,如果我们想要解决上述问题,我们就要满足我们的第二范式,我们可以将上述的成绩表进行拆分,分为学生表,课程表,成绩表

  此时我们的学生表和课程表的非关键字段是和我们的各自的主键id列,完全依赖的,同时这两个

  表的每一列都可以用基本数据类型表示,那么这两个列也是天然满足第一范式的。

  此时我们得到了上述的两个表,接下我们就可以设计得到我们的成绩表了,根据我们的学生id和课程id,得到成绩表的复合主键,根据这个复合主键的对应关系就能得到了我们哪个学生,参加了哪门考试得到了什么成绩。这样就不存在数据冗余和部分函数依赖,同时我们要单独插入或删除我们的学生信息和课程信息也是可以的。

  注意:我们的第二范式强调的是部分函数依赖,如果我们的表中主键只有一个列,那么我们就说它是天然满足第二范式的。

三、第三范式

定义:在满足第二范式的基础上,不存在非关键字段,对任一候选键的传递依赖。

   我们来看下面这张学生表:

  在这张表中,我们可以根据学号去得到我们学生的所在学院,同时也可以得到学院的电话和邮箱,但其实我们知道正常来说,一个学生的学号是不可能得到,他所在学院的电话和邮箱的,而这种由学号->学院->学院电话的传递关系,我们就称它为传递依赖。

  而为了防止这种传递依赖我们就引入了新的规范:第三范式。

  我们可以将上表拆分成两个表,学生表和学院表

  我们可以通过学院编号进行外键的链接,这样我们的学号就只能找到我们的学生信息,而学院的信息需要通过学院编号来获得, 这样就解决了我们的传递依赖。

 四、设计

1、从设计上来说,我们要从现实业务中抽象得到概念类

2、然后从中确定实体和实体之间的关系,并画出E-R图

3、最后根据我们的E-R图完成我们SQL语句的编写并创建数据库

而我们这里的E-R图又称实体-关系图,它是由三个部分所组成的分别是:实体,属性,关系

  • 实体:即数据对象,用矩形框表示。
  • 属性:实体的特性,用椭圆形或圆角矩形表示
  • 关系:实体之间的联系,用菱形框表示,并标明关系的类型,并用直线将相关实体与关系连接起来。

而对于这种实体间的关系,由分为三种:一对一关系、一对多关系、多对多关系。 

(1)一对一关系

比如我们的用户实体与账户实体就是一对一的关系。

即一个用户的信息只能登录一个账户。

(2)一对多关系

比如我们的学生实体和班级实体,就是一对多的关系。

即一个班级里有多个学生。

(3)多对多关系

比如我们的学生实体和选课实体,就是多对多的关系

即一个学生可以选多门课程,一门课程也可以被多个学生选。

对于多对多关系,我们也可以使用中间表进行记录,比如一个学生参加了某一门课程的考试得到了相应的成绩。


好了,今天的分享就到这里了,还请大家多多关注,我们下一篇见!

相关文章:

MySQL:数据库设计

目录 一、范式 二、第一范式 二、第二范式 三、第三范式 四、设计 (1)一对一关系 (2)一对多关系 (3)多对多关系 一、范式 数据库的范式是一种规则(规范),如果我们…...

Android Kotlin AIDL 完整实现与优化指南

本文将详细介绍如何在Android中使用Kotlin实现AIDL(Android Interface Definition Language),并提供多种优化方案。 一、基础实现 1. 创建AIDL文件 在src/main/aidl/com/example/myapplication/目录下创建: IMyAidlInterface.…...

synchronized关键字的实现

Java对象结构 synchronized锁升级过程 为了优化synchronized锁的效率,在JDK6中,HotSpot虚拟机开发团队提出了锁升级的概念,包括偏向锁、轻量级锁、重量级锁等,锁升级指的就是“无锁 --> 偏向锁 --> 轻量级锁 --> 重量级…...

Ubuntu K8s集群安全加固方案

Ubuntu K8s集群安全加固方案 在Ubuntu系统上部署Kubernetes集群时,若服务器拥有外网IP,需采取多层次安全防护措施以确保集群安全。本方案通过系统防火墙配置、TLS通信启用、网络策略实施和RBAC权限控制四个核心层面,构建安全的Kubernetes环境…...

如何在spark里搭建local模式

在Spark里搭建local模式较为简单,下面详细介绍在不同环境下搭建local模式的步骤。 ### 环境准备 - **Java**: Spark是基于Java虚拟机(JVM)运行的,所以要安装Java 8及以上版本。 - **Spark**: 可从[Apache…...

opencv 图像的旋转

图像的旋转 1 单点旋转2. 图片旋转(cv2.getRotationMatrix2D)3. 插值方法3.1 最近邻插值(cv2.INTER_NEAREST)3.2 双线性插值(cv2.INTER_LINEAR)3.3 像素区域插值(cv2.INTER_AREA)3.4 双三次插值(cv2.INTER_CUBIC&#…...

【DNS】BIND 9的配置

该文档围绕BIND 9的配置与区域文件展开,介绍了BIND 9配置文件及区域文件的相关知识,以及权威名称服务器、解析器的相关内容,还阐述了负载均衡和区域文件的详细知识,具体如下: 基础配置文件: named.conf&am…...

Spring Boot常用注解详解:实例与核心概念

Spring Boot常用注解详解:实例与核心概念 前言 Spring Boot作为Java领域最受欢迎的快速开发框架,其核心特性之一是通过注解(Annotation)简化配置,提高开发效率。注解驱动开发模式让开发者告别繁琐的XML配置&#xff…...

【多线程】线程互斥 互斥量操作 守卫锁 重入与线程安全

文章目录 Ⅰ. 线程互斥概念Ⅱ. 互斥锁的概念Ⅲ. 互斥锁的接口一、互斥锁的定义二、初始化互斥锁三、销毁互斥锁四、互斥量的加锁和解锁① 加锁接口② 解锁接口五、改进买票系统💥注意事项Ⅳ. 互斥锁的实现原理一、问题引入二、复习知识三、实现原理Ⅴ. 封装锁对象 &&…...

[原创](现代Delphi 12指南):[macOS 64bit App开发]:如何使用NSString类型字符串?

[作者] 常用网名: 猪头三 出生日期: 1981.XX.XX 企鹅交流: 643439947 个人网站: 80x86汇编小站 编程生涯: 2001年~至今[共24年] 职业生涯: 22年 开发语言: C/C++、80x86ASM、Object Pascal、Objective-C、C#、R、Python、PHP、Perl、 开发工具: Visual Studio、Delphi、XCode、…...

Python协程详解:从基础到实战

协程是Python中实现并发编程的重要方式之一,它比线程更轻量级,能够高效处理I/O密集型任务。本文将全面介绍协程的概念、原理、实现方式以及与线程、进程的对比,包含完整的效率对比代码和详细说明,帮助Python开发者深入理解并掌握协…...

学习笔记(C++篇)--- Day 4

目录 1.赋值运算符重载 1.1 运算符重载 1.2 赋值运算符重载 1.3 日期类实现 1.赋值运算符重载 1.1 运算符重载 ①当运算符被用于类类型的对象时,C语言允许我们通过通过运算符重载的形式指定新的含义。C规定类类型对象使用运算符时,必须转换成调用对…...

空闲列表:回收和再利用

空闲列表:回收和再利用 手动与自动内存管理 手动管理:程序员需要明确地分配和释放内存。自动管理:例如使用垃圾收集器(GC),它能够自动检测并回收未使用的对象,不需要程序员干预。 对于某些数据结构如B树,…...

504 nginx解决方案

当遇到 504 Gateway Time-out 错误时,通常是因为 Nginx 作为反向代理等待后端服务(如 PHP-FPM、Java 应用等)响应的时间超过了预设的超时阈值。以下是详细的解决方案,结合知识库中的信息整理而成: 一、核心原因分析 后…...

【消息队列RocketMQ】五、RocketMQ 实战应用与生态拓展

本篇文章主要将结合前面几篇文章的基础讲解,来演示RocketMQ的实际场景中的应用。 一、RocketMQ 实战应用场景​ 1.1 电商系统中的应用​ 在电商系统中,RocketMQ 承担着重要角色。以双十一大促活动为例,短时间内会产生海量的订单请求、库存…...

volatile怎么保证可见性和有序性?(个人理解)

volatile怎么保证可见性和有序性? volatile变量会在字段修饰符中显示ACC_VOLATILE。通过插入内存屏障指令,禁止指令重排序。不管前面与后面任何指令,都不能与内存屏障指令进行重排,保证前后的指令按顺序执行 。同时保证数据修改的…...

计算机组成与体系结构:直接内存映射(Direct Memory Mapping)

目录 CPU地址怎么找到真实的数据? 内存映射的基本单位和结构 1. Pages(页)——虚拟地址空间的基本单位 2. Frames(页框)——物理内存空间的基本单位 3. Blocks(块)——主存和缓存之间的数据…...

RAGFlow:构建高效检索增强生成流程的技术解析

引言 在当今信息爆炸的时代,如何从海量数据中快速准确地获取所需信息并生成高质量内容已成为人工智能领域的重要挑战。检索增强生成(Retrieval-Augmented Generation, RAG)技术应运而生,它将信息检索与大型语言模型(L…...

STM32提高篇: 蓝牙通讯

STM32提高篇: 蓝牙通讯 一.蓝牙通讯介绍1.蓝牙技术类型 二.蓝牙协议栈1.蓝牙芯片架构2.BLE低功耗蓝牙协议栈框架 三.ESP32-C3中的蓝牙功能1.广播2.扫描3.通讯 四.发送和接收 一.蓝牙通讯介绍 蓝牙,是一种利用低功率无线电,支持设备短距离通信的无线电技…...

SpringMVC处理请求映射路径和接收参数

目录 springmvc处理请求映射路径 案例:访问 OrderController类的pirntUser方法报错:java.lang.IllegalStateException:映射不明确 核心错误信息 springmvc接收参数 一 ,常见的字符串和数字类型的参数接收方式 1.1 请求路径的…...

高质量学术引言如何妙用ChatGPT?如何写提示词

目录 1、引言究竟是什么? 2、引言如何构建?? 在学术写作领域,巧妙利用人工智能来构建文章的引言和理论框架是一个尚待探索的领域。小编在这篇文章中探讨一种独特的方法,即利用 ChatGPT 作为工具来构建引言和理论框架…...

【程序员 NLP 入门】词嵌入 - 上下文中的窗口大小是什么意思? (★小白必会版★)

🌟 嗨,你好,我是 青松 ! 🌈 希望用我的经验,让“程序猿”的AI学习之路走的更容易些,若我的经验能为你前行的道路增添一丝轻松,我将倍感荣幸!共勉~ 【程序员 NLP 入门】词…...

从物理到预测:数据驱动的深度学习的结构化探索及AI推理

在当今科学探索的时代,理解的前沿不再仅仅存在于我们书写的方程式中,也存在于我们收集的数据和构建的模型中。在物理学和机器学习的交汇处,一个快速发展的领域正在兴起,它不仅观察宇宙,更是在学习宇宙。 AI推理 我们…...

各种各样的bug合集

一、连不上数据库db 1.可能是密码一大包东西不对; 2.可能是里面某个port和数据库不一样(针对于修改了数据库但是连不上的情况); 3.可能是git代码没拉对,再拉一下代码。❤ 二、没有这个包 可能是可以#注释掉。❤ …...

大模型AI的“双刃剑“:数据安全与可靠性挑战与破局之道

在数字经济蓬勃发展的浪潮中,数据要素已然成为驱动经济社会创新发展的核心引擎。从智能制造到智慧城市,从电子商务到金融科技,数据要素的深度融合与广泛应用,正以前所未有的力量重塑着产业格局与经济形态。 然而,随着…...

如何使用 CompletableFuture、Function 和 Optional 优雅地处理异步编程?

当异步遇上函数式编程,代码变得更优雅 在日常开发中,很多时候我们需要处理异步任务、函数转换和空值检查。传统的回调方式和空值判断常常让代码看起来繁琐而难以维护。幸运的是,Java 提供了 CompletableFuture、Function 和 Optional&#x…...

基于大模型的结肠癌全病程预测与诊疗方案研究

目录 一、引言 1.1 研究背景与意义 1.2 研究目的与创新点 二、结肠癌概述 2.1 流行病学特征 2.2 发病机制与危险因素 2.3 临床症状与诊断方法 三、大模型技术原理与应用现状 3.1 大模型的基本原理 3.2 在医疗领域的应用情况 3.3 在结肠癌预测中的潜力分析 四、术前…...

操作系统概述与安装

主流操作系统概述 信创平台概述 虚拟机软件介绍与安装 windows server 安装 centos7 安装 银河麒麟V10 安装 一:主流服务器操作系统 (1)Windows Server 发展历程: 1993年推出第一代 WindowsNT(企业级内核&am…...

算法设计与分析(基础)

问题列表 一、 算法的定义与特征,算法设计的基本步骤二、 算法分析的目的是什么?如何评价算法,如何度量算法的复杂性?三、 递归算法、分治法、贪婪法、动态规划法、回溯法的基本思想方法。四、 同一个问题,如TSP&#…...

多线程(线程安全)

一、线程安全的风险来源 1.1 后厨的「订单撞单」现象 场景:两服务员同时录入客人点单到同一个菜单本 问题: 订单可能被覆盖菜品数量统计错误 Java中的表现: public class OrderServlet extends HttpServlet {private int totalOrders 0…...