数据库的规范化设计方法---3种范式

第一范式(1NF):确保表中的每个字段都是不可分割的基本数据项。
第二范式(2NF):在满足1NF的基础上,确保非主属性完全依赖于主键。
第三范式(3NF):在满足2NF的基础上,确保非主属性不传递依赖于主键。

使用 StudentCourse 表作为基础,来解释第一范式(1NF)。

第一范式 (1NF) 的核心要求:
确保表中的每一个单元格(字段值)都包含单一、不可再分割的基本数据项。换句话说,表中的每一列都必须是原子性的,不能包含多个值或复合值。
回顾之前的 StudentCourse 表:

StudentID (学号)StudentName (姓名)StudentDepartment (系别)CourseID (课程号)CourseName (课程名)Professor (教授)
1001张三计算机系CS101数据结构李教授
1001张三计算机系CS201数据库原理王教授
1002李四电子系EE101电路基础赵教授
1003王五计算机系CS101数据结构李教授
1003王五计算机系CS301操作系统刘教授

分析 StudentCourse 表是否满足 1NF:
现在我们来逐一检查这个表中的每一列,看看它们是否都满足原子性(不可分割)的要求:

  1. StudentID (学号): 例如 “1001”。这是一个单一的数值,不能再分割成更小的有意义的部分(比如不能把它分成 ‘1’, ‘0’, ‘0’, ‘1’ 并认为每个都有独立意义)。满足 1NF。
  2. StudentName (姓名): 例如 “张三”。虽然姓名可以拆分成姓氏和名字(“张” 和 “三”),但在数据库设计中,通常将整个姓名视为一个不可分割的字符串来处理,特别是当我们不需要单独查询姓氏或名字时。如果业务上需要单独处理姓氏和名字,才需要拆分成两列。通常认为满足 1NF。
  3. StudentDepartment (系别): 例如 “计算机系”。这是一个单一的文本值,表示一个系别。满足 1NF。
  4. CourseID (课程号): 例如 “CS101”。这是一个单一的标识符,不能再分割。满足 1NF。
  5. CourseName (课程名): 例如 “数据结构”。这是一个单一的文本值。满足 1NF。
  6. Professor (教授): 例如 “李教授”。这是一个单一的文本值。满足 1NF。
    结论: 在这个例子中,StudentCourse 表的每一列都只包含单一、不可分割的数据项。因此,这个表满足第一范式 (1NF)
    一个不满足 1NF 的例子:
    假设我们有一个 StudentInfo 表,其中存储了学生的联系电话,但允许一个学生有多个电话:
StudentIDStudentNamePhoneNumbers
1001张三13812345678, 13987654321
1002李四13700001111
1003王五13611112222, 13833334444, 13955556666

在这个表中,PhoneNumbers 列包含了多个电话号码,用逗号分隔。这违反了 1NF,因为该列的单元格包含了多个基本数据项(多个电话号码)。
要使其满足 1NF,我们需要将每个电话号码放在单独的一行,或者创建一个单独的 StudentPhone 表。
希望这个例子能帮助你理解第一范式的要求!

好的,我们来通过具体的例子来解释“完全依赖”和“不传递依赖”这两个概念,它们是第二范式(2NF)和第三范式(3NF)的核心。
假设我们有一个存储学生选修课程信息的表:
表:StudentCourse (学生选课表)

StudentID (学号)StudentName (姓名)StudentDepartment (系别)CourseID (课程号)CourseName (课程名)Professor (教授)
1001张三计算机系CS101数据结构李教授
1001张三计算机系CS201数据库原理王教授
1002李四电子系EE101电路基础赵教授
1003王五计算机系CS101数据结构李教授
1003王五计算机系CS301操作系统刘教授

这个表的主键是 (StudentID, CourseID),因为一个学生可以选多门课,一门课可以被多个学生选,只有同时知道学号和课程号才能唯一确定一行记录。

2. 第二范式 (2NF) - 完全依赖 (Full Dependency)

定义: 在满足第一范式(1NF)的基础上,非主属性必须完全依赖于整个主键,而不仅仅是主键的一部分。
问题: 如果主键是由多个属性组成的(复合主键),我们需要检查每个非主属性是否依赖于所有主键属性。
在 StudentCourse 表中:

  • 主键: (StudentID, CourseID)
  • 非主属性: StudentName, StudentDepartment, CourseName, Professor
    现在我们检查每个非主属性是否完全依赖于 (StudentID, CourseID)
  1. StudentName (姓名): 姓名是由学号 StudentID 决定的,和选了哪门课 CourseID 无关。所以 StudentName 依赖于 StudentID,而不是 (StudentID, CourseID)。这叫部分依赖 (Partial Dependency)
  2. StudentDepartment (系别): 系别也是由学号 StudentID 决定的,和课程号 CourseID 无关。所以 StudentDepartment 依赖于 StudentID,而不是 (StudentID, CourseID)。这也是部分依赖
  3. CourseName (课程名): 课程名是由课程号 CourseID 决定的,和学生的学号 StudentID 无关。所以 CourseName 依赖于 CourseID,而不是 (StudentID, CourseID)。这同样是部分依赖
  4. Professor (教授): 教授通常是由课程号 CourseID 决定的(假设一门课只有一个固定教授),和学生的学号 StudentID 无关。所以 Professor 依赖于 CourseID,而不是 (StudentID, CourseID)。这也是部分依赖
    结论: StudentCourse 表不满足 2NF,因为存在非主属性(StudentName, StudentDepartment, CourseName, Professor)部分依赖于主键 (StudentID, CourseID) 的子集(要么只依赖 StudentID,要么只依赖 CourseID)。
    如何修正 (分解): 我们需要将表分解,使得每个表的非主属性都完全依赖于该表的主键。
  • Student (学生表): 主键 StudentID
    StudentID (学号)StudentName (姓名)StudentDepartment (系别)
    1001张三计算机系
    1002李四电子系
    1003王五计算机系
  • Course (课程表): 主键 CourseID
    CourseID (课程号)CourseName (课程名)Professor (教授)
    CS101数据结构李教授
    CS201数据库原理王教授
    EE101电路基础赵教授
    CS301操作系统刘教授
  • StudentSC (学生选课关系表): 主键 (StudentID, CourseID)
    StudentID (学号)CourseID (课程号)
    1001CS101
    1001CS201
    1002EE101
    1003CS101
    1003CS301

现在检查这些新表:

  • Student 表的主键是 StudentID,所有非主属性 (StudentName, StudentDepartment) 都完全依赖于 StudentID
  • Course 表的主键是 CourseID,所有非主属性 (CourseName, Professor) 都完全依赖于 CourseID
  • StudentSC 表的主键是 (StudentID, CourseID),它没有其他非主属性,所以自然满足。
    这些分解后的表都满足了 2NF。

3. 第三范式 (3NF) - 不传递依赖 (No Transitive Dependency)

定义: 在满足第二范式(2NF)的基础上,非主属性必须不传递依赖于主键。也就是说,非主属性不能依赖于另一个非主属性。
问题: 我们需要检查是否存在“主键 -> 非主属性 A -> 非主属性 B”这样的依赖链条,其中 B 就是传递依赖于主键。
在修正后的 Student 表中:

  • 主键: StudentID
  • 非主属性: StudentName, StudentDepartment
    检查是否存在传递依赖:
  • StudentID -> StudentDepartment (学号决定系别)
  • StudentDepartment -> ? 这个系别 (StudentDepartment) 是否又决定了其他的非主属性?在我们的 Student 表中,系别只决定了它自己,没有决定其他非主属性 (StudentName)。所以没有传递依赖。
    在修正后的 Course 表中:
  • 主键: CourseID
  • 非主属性: CourseName, Professor
    检查是否存在传递依赖:
  • CourseID -> Professor (课程号决定教授)
  • Professor -> ? 这个教授 (Professor) 是否又决定了其他的非主属性?在我们的 Course 表中,教授只决定了它自己,没有决定其他非主属性 (CourseName)。所以没有传递依赖。
    假设我们有一个不满足 3NF 的表:
    表:StudentDept (学生系别表 - 假设大学有系主任)
StudentID (学号)StudentName (姓名)StudentDepartment (系别)DepartmentHead (系主任)
1001张三计算机系陈主任
1002李四电子系吴主任
1003王五计算机系陈主任
  • 主键: StudentID (假设学号唯一)
  • 非主属性: StudentName, StudentDepartment, DepartmentHead
    检查依赖关系:
  1. StudentID -> StudentName (满足)
  2. StudentID -> StudentDepartment (满足)
  3. StudentID -> DepartmentHead ? 不完全是。学号本身不直接决定系主任。但是,我们可以通过学号找到系别 (StudentID -> StudentDepartment),然后通过系别找到系主任 (StudentDepartment -> DepartmentHead)。所以,DepartmentHead传递依赖于主键 StudentID 的。StudentID -> StudentDepartment -> DepartmentHead
    结论: StudentDept 表不满足 3NF,因为存在非主属性 DepartmentHead 传递依赖于主键 StudentID
    如何修正 (分解): 我们需要将传递依赖的非主属性分离出来。
  • Student (学生表): 主键 StudentID
  • StudentID (学号)StudentName (姓名)StudentDepartment (系别)
    1001张三计算机系
    1002李四电子系
    1003王五计算机系
  • Department (系别表): 主键 StudentDepartment (可以用系别名称或系编号作为主键,这里简化用名称)
    StudentDepartment (系别)DepartmentHead (系主任)
    计算机系陈主任
    电子系吴主任

现在检查这些新表:

  • Student 表满足 3NF。
  • Department 表的主键是 StudentDepartment,唯一的非主属性 DepartmentHead 完全依赖于它,并且没有其他非主属性可以依赖,所以也满足 3NF。

总结:

  • 完全依赖 (2NF): 非主属性不能只依赖于复合主键的“一部分”。它们必须依赖于整个主键。
  • 不传递依赖 (3NF): 非主属性不能依赖于另一个非主属性。它们必须直接依赖于主键,不能通过中间的非主属性间接依赖。
    通过满足这些范式,可以减少数据冗余,避免数据更新异常(插入、删除、修改异常)。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

产品经理入门(2)产品体验报告

产品体验报告大纲:重点在产品体验——优点。 1.产品概括 可以从各大平台搜产品介绍。 2.市场分析 按照产品方向分析各个指标——包括有效使用时间,市场规模等。 3. 用户分析——对用户通过各项指标画像。 4.产品体验——对各项功能与设计的体验。 5.报告总结

[Java][Leetcode simple] 13. 罗马数字转整数

一、自己想的 只有提到的六种情况是-&#xff0c;其他都是 public int romanToInt1(String s) {int res 0;int n s.length();Map<Character, Integer> map new HashMap<>();map.put(I, 1);map.put(V, 5);map.put(X, 10);map.put(L, 50);map.put(C, 100);map.pu…

如何在 CentOS 7 虚拟机上配置静态 IP 地址并保持重启后 SSH 连接

在使用 CentOS 7 的虚拟机时&#xff0c;我们通常需要配置静态 IP 地址&#xff0c;以确保在每次虚拟机重启后能够通过 SSH 连接。本文将介绍如何在 CentOS 7 系统中配置静态 IP 地址&#xff0c;并确保配置在系统重启后依然生效。 步骤 1&#xff1a;检查虚拟机网络接口 首先…

matlab求解问题

一、目的 掌握Matlab中函数求导、函数极值和极限问题的求解,能够借助Matlab工具对简单优化模型进行求解。 二、内容与设计思想 1、函数求导 1.1求解给定函数的一阶导数&#xff1a;diff(y, x)用于对变量x求y的导数。 1.2求解给定函数的二阶导数&#xff1a;在求出一阶导数的…

C语言斐波那契数列

斐波那契数列&#xff08;Fibonacci sequence&#xff09;&#xff0c;又称黄金分割数列 、兔子数列。由意大利数学家莱昂纳多・斐波那契在 1202 年提出&#xff0c;源于其《算盘书》中一道兔子繁殖问题。定义&#xff1a;在数学上&#xff0c;该数列以递归形式定义。最常见的是…

AI浪潮:开启科技新纪元

AI 的多面应用​ AI 的影响力早已突破实验室的围墙&#xff0c;在众多领域落地生根&#xff0c;成为推动行业变革的重要力量。 在医疗领域&#xff0c;AI 宛如一位不知疲倦的助手&#xff0c;助力医生提升诊疗效率与准确性。通过对海量医学影像的深度学习&#xff0c;AI 能够快…

Ansys 计算刚柔耦合矩阵系数

Ansys 计算刚柔耦合系数矩阵 文章目录 Ansys 计算刚柔耦合系数矩阵卫星的刚柔耦合动力学模型采用 ANSYS 的 APDL 语言的计算方法系统转动惯量的求解方法参考文献 卫星的刚柔耦合动力学模型 柔性航天器的刚柔耦合动力学模型可以表示为 m v ˙ B t r a n η F J ω ˙ ω J…

算法题(148):排座椅

审题&#xff1a; 本题需要我们找到最佳的排座椅方案&#xff0c;并输出行&#xff0c;列方案 思路&#xff1a; 方法一&#xff1a;简单贪心 由于题目会告诉我们有哪几对的同学会交头接耳&#xff0c;所以我们可以记录下第几行/第几列上可以隔开的同学对数&#xff0c;而题目限…

企业级电商数据对接:1688 商品详情 API 接口开发与优化实践

在数字化浪潮席卷全球的当下&#xff0c;企业级电商平台之间的数据对接已成为提升运营效率、增强市场竞争力的关键环节。作为国内知名的 B2B 电商平台&#xff0c;1688 拥有海量商品资源&#xff0c;通过开发和优化商品详情 API 接口&#xff0c;企业能够快速获取商品信息&…

【Cesium入门教程】第七课:Primitive图元

Cesium丰富的空间数据可视化API分为两部分&#xff1a;primitive API面向三维图形开发者&#xff0c;更底层一些。 Entity API是数据驱动更高级一些。 // entity // 调用方便&#xff0c;封装完美 // 是基于primitive的封装// primitive // 更接近底层 // 可以绘制高级图形 /…

Oracle APEX 必须输入项目标签型号显示位置

1. 正常Oracle APEX中必须输入项目标签的红星显示在标签文字左侧&#xff0c;偏偏项目要求显示在右侧&#xff0c; 加入如下全局CSS代码 .t-Form-label {display: flex;flex-direction: row-reverse;gap: 1px; }以上。

深入理解 TypeScript 中的 unknown 类型:安全处理未知数据的最佳实践

在 TypeScript 的类型体系中&#xff0c;unknown 是一个极具特色的类型。它与 any 看似相似&#xff0c;却在安全性上有着本质差异。本文将从设计理念、核心特性、使用场景及最佳实践等方面深入剖析 unknown&#xff0c;帮助开发者在处理动态数据时既能保持灵活性&#xff0c;又…

项目QT+ffmpeg+rtsp(二)——海康威视相机测试

文章目录 前言一、验证RTSP地址的有效性1.1 使用VLC播放器验证1.2 使用FFmpeg命令行验证1.3 使用Python代码检查网络连接1.4 检查摄像头Web界面1.5 使用RTSP客户端工具二、关于IPV4的地址2.1 原来2.1.1 原因2.2 解决2.3 显示前言 昨晚拿到一个海康威视的相机,是连接上了交换机…

Java-Collections类高效应用的全面指南

Java-Collections类高效应用的全面指南 前言一、Collections 类概述二、Collections 类的基础方法2.1 排序操作2.1.1 sort方法2.1.2 reverse方法2.1.3 shuffle方法 2.2 查找与替换操作2.2.1 binarySearch方法2.2.2 max和min方法2.2.3 replaceAll方法 三、Collections 类的高级应…

中国30米年度土地覆盖数据集及其动态变化(1985-2022年)

中文名称 中国30米年度土地覆盖数据集及其动态变化(1985-2022年) 英文名称&#xff1a;The 30 m annual land cover datasets and its dynamics in China from 1985 to 2022 CSTR:11738.11.NCDC.ZENODO.DB3943.2023 DOI 10.5281/zenodo.8176941 数据共享方式&#xff1a…

Python高版本降低低版本导致python导包异常的问题

当Python从高版本降级到低版本后出现导包异常&#xff0c;通常是由于以下原因导致的&#xff1a;高版本中安装的包与低版本不兼容、包路径或依赖冲突、虚拟环境未正确配置等。以下是具体的解决方案和步骤&#xff1a; 1. 确认问题原因 检查Python版本&#xff1a;确保当前使用…

AGI大模型(20):混合检索之rank_bm25库来实现词法搜索

1 混合检索简介 混合搜索结合了两种检索信息的方法 词法搜索 (BM25) :这种传统方法根据精确的关键字匹配来检索文档。例如,如果您搜索“cat on the mat”,它将找到包含这些确切单词的文档。 基于嵌入的搜索(密集检索) :这种较新的方法通过比较文档的语义来检索文档。查…

掌握 Kotlin Android 单元测试:MockK 框架深度实践指南

掌握 Kotlin Android 单元测试&#xff1a;MockK 框架深度实践指南 在 Android 开发中&#xff0c;单元测试是保障代码质量的核心手段。但面对复杂的依赖关系和 Kotlin 语言特性&#xff0c;传统 Mock 框架常显得力不从心。本文将带你深入 MockK —— 一款专为 Kotlin 设计的 …

常见平方数和立方数的计算

平方数&#xff08;n&#xff09; 数字计算过程结果1010 101001111 111211212 121441313 131691414 141961515 152251616 162561717 172891818 183241919 193612020 20400 立方数&#xff08;n&#xff09; 数字计算过程结果1010 10 101,0001111 11 111,33112…

自动化测试实战 - 博客系统自动化测试

目录 1. 前言 2. 自动化实施步骤 3. 页面分析 4. 设计测试用例 5. 搭建自动化环境 6. 编写自动化代码 6.1 准备工作 - Utils 6.1.1 允许远程自动化 & 创建驱动 6.1.2 实现自动化截图 6.1.3 释放 WebDriver 6.2 自动化测试登录页 - LoginTest 6.2.1 打开登陆页 …