关系数据库设计:DBMS
Jan 05, 2025 pm 12:57 PM关系数据库设计:综合指南
关系数据库设计是有效数据库系统的基石,专注于有效组织数据,同时减少冗余并保持数据完整性。本文对分解、规范化、函数依赖和键进行了彻底的探索,确保您完全理解关系数据库设计原则。
关系数据库设计中的分解
分解是将一个大的关系(表)分解成更小的、有意义的关系,以消除冗余、提高一致性并优化性能的过程。这是正常化的一个关键方面。
分解类型
-
有损分解:
- 如果原始表无法通过连接分解的关系来完美重建,则分解是有损。
- 当分解过程中某些数据或关系丢失时,就会发生这种情况。
- 示例: 考虑下表:
1
2
3
4
EmployeeID | ProjectID | ProjectManager
---------------------------------------
E1 | P1 | M1
E2 | P1 | M1
登录后复制登录后复制登录后复制登录后复制登录后复制登录后复制登录后复制如果将其分解为:
- 表 1:员工 ID |项目ID
- 表 2:项目 ID |专案经理 重新连接这些表可能会导致数据重复或不一致,从而导致有损分解。
-
无损分解:
- 如果可以通过连接分解的关系来完美地重建原始表,而不会丢失任何数据或引入不一致,那么分解就是无损。
- 当分解保留所有函数依赖关系或每个分解关系中包含关键属性时,即可实现这一点。
功能依赖
函数依赖 (FD) 描述关系中两个属性之间的关系,其中一个属性(或属性集)的值决定另一个属性(或属性集)的值。它是关系数据库设计和规范化中的基本概念。
定义:令 X 和 Y 为关系 R 中的属性集。函数依赖
X → Y 意味着对于 R 中的任意两个元组(行),如果元组在 X 的值上一致,他们还必须就 Y 的值达成一致。
- X:行列式(左侧的属性)。
- Y:依赖(右侧的属性)。
考虑一个存储学生信息的表:
1 2 3 4 5 |
|
函数依赖的属性:
- 自反性:如果 Y 是 X 的子集,则 X → Y。
- 增强:如果 X → Y,则 XZ → YZ(向两侧添加属性保留依赖关系)。
- 传递性:如果 X → Y 且 Y → Z,则 X → Z。
关系数据库中的键
键对于唯一标识表中的记录和强制数据完整性至关重要。
钥匙类型:
-
超级键:
- 一组一个或多个属性,可以唯一标识关系中的元组。
- 示例:在具有 EmployeeID 和 Name 属性的表中,{EmployeeID}、{EmployeeID, Name} 是超级键。
-
候选密钥:
- 最小的超级键,意味着它的没有适当的子集也是超级键。
- 示例:如果 {EmployeeID} 可以唯一标识一个元组,则它是候选键。
-
主键:
- 数据库设计者选择的候选键,用于唯一标识元组。
- 示例:Employee 表中的 EmployeeID。
-
外键:
- 一个表中的属性(或一组属性)引用另一个表中的主键,从而在表之间建立关系。
- 示例:员工表中的 DepartmentID 引用部门表中的 DepartmentID。
-
复合键:
- 由两个或多个属性组成的主键。
- 示例:学生注册表中的(StudentID、CourseID)。
-
唯一密钥:
- 一个键约束,确保列(或列组合)中的所有值都是唯一的。
规范化和范式
标准化是组织属性和关系以减少冗余和依赖性、确保数据完整性的过程。这是通过逐步满足连续范式的标准来实现的。
范式(综合概述)
第一范式 (1NF)
定义:
如果关系满足以下条件,则称其为 第一范式 (1NF):
- 原子性:所有属性(列)必须包含原子值。这意味着每列中的值是不可分割的并且不能进一步细分。
- 单值条目:表中的每一列都应包含单一数据类型的值,并且任何列都不应包含集合、列表或数组。
- 行的唯一性:每一行必须是唯一的,这意味着表应该有一个主键来区分行。
- 无重复组:表格不应具有同一属性的多个列(如 Item1、Item2 等),也不应在单个单元格中存储多个值。
说明:
- 原子值:每个单元格中的数据必须采用最简单的形式。例如,每个项目应该占据自己的行,而不是在一个单元格中存储多个项目。
- 重复组:这是多列或多行代表相同类型数据的地方,使得表不符合 1NF。
- 主键:主键确保每一行都是唯一可识别的,这是关系数据库的基本要求。
示例:
不合规表(不在 1NF 中):
1 2 3 4 |
|
- Items 列违反了原子性,因为它包含多个值(例如,“笔,笔记本”)。
- 存在重复的组,因为项目存储在单个单元格中而不是单独的行中。
合规表(在 1NF 中):
1 2 3 4 5 |
|
- 这里,项目列被分解为原子值,每个项目位于单独的行中。
- 没有一个单元格包含多个值,确保原子性。
- 该表没有重复的组或数组,使其符合 1NF。
第二范式 (2NF)
定义:
如果满足以下条件,则关系处于 第二范式 (2NF):
- 它已经处于第一范式(1NF)(即没有多值或重复组)。
- 每个非主属性在功能上完全依赖于整个主键。
- 非素数属性:不属于任何候选键的属性。
- 完全功能依赖:非素数属性必须依赖于整个复合主键,而不仅仅是其中的一部分。
说明:
- 当非主属性仅依赖于复合主键的一部分而不是整个键时,就会发生部分依赖。
- 2NF 通过将关系分解为更小的关系来消除部分依赖,确保非素数属性仅依赖于整个主键或另一个候选键。
这一步减少了部分依赖造成的冗余,更好地组织数据。
示例:
不合规表(不在 2NF 中):
考虑一个存储学生课程信息的表:
1 2 3 4 |
|
- 复合主键:(StudentID,CourseID)。
-
部分依赖:
- 教师和部门仅依赖于 CourseID,而不依赖于整个主键(StudentID、CourseID)。
这违反了 2NF,因为非主属性(讲师和部门)部分依赖于组合键。
兼容表(在 2NF 中):
要删除部分依赖关系,请将表分解为两个关系:
- 学生课程表:
1 2 3 4 5 |
|
- 课程详情表:
1 2 3 4 |
|
第三范式 (3NF)
定义:
如果满足以下条件,则关系处于 第三范式 (3NF):
- 它采用第二范式(2NF)(即没有部分依赖)。
-
不存在传递依赖,这意味着:
- 没有一个非主属性依赖于另一个非主属性。
- 非主属性应该仅依赖于候选键,而不是通过另一个非主属性。
- 非素数属性:不属于任何候选键的属性。
- 传递依赖:非主属性通过另一个非主属性间接依赖于候选键的依赖。
说明:
在 3NF 中,我们消除传递依赖以减少冗余并提高数据一致性。
- 传递依赖示例:如果 A → B 且 B → C,则 A → C 是传递依赖。这意味着 C 通过 B 间接依赖于 A。
- 此类依赖关系会引入冗余,因为对 B 的更改可能会导致更新 C 时出现异常。
示例:
不合规表(不在 3NF 中):
1 2 3 4 5 |
|
候选键:StudentID 唯一标识每一行。
-
问题:HOD属性取决于Department,而不是直接取决于StudentID。
- 学生 ID → 部门(直接依赖)。
- 部门 → HOD(传递依赖)。
- 因此,StudentID → HOD 是传递依赖。
这种结构会导致冗余:如果 CS 部门的 HOD 发生变化,则需要更新多行。
兼容表(在 3NF 中):
要解决传递依赖关系,请将表分解为两个关系:
- 学生系表:
1 2 3 4 |
|
- 部门-HOD表:
1 2 3 4 5 |
|
Boyce-Codd 范式 (BCNF)
定义:
如果满足以下条件,则关系处于 Boyce-Codd 范式 (BCNF):
- 它采用第三范式(3NF)(即不存在部分或传递依赖)。
- 每个行列式都是一个候选键。
- 行列式:另一个属性在功能上依赖的一个属性(或一组属性)。
- 候选键:可以唯一标识关系中每个元组的最小属性集。
3NF 和 BCNF 之间的主要区别:
- 虽然 3NF 允许某些依赖关系,其中非素数属性在功能上依赖于候选键,但 BCNF 通过确保每个行列式都是候选键来消除任何此类异常情况。
说明:
BCNF 比 3NF 更严格,解决了关系可能满足 3NF 但仍然具有由于违反 BCNF 的依赖关系而导致的冗余的情况。
何时需要 BCNF:
- 当非候选键属性决定了候选键的一部分,导致冗余和异常时,BCNF 是必要的。
示例:
不合规表(不在 BCNF 中):
1 2 3 4 |
|
函数依赖:
- 课程ID → 讲师
- 教练 → 房间
候选键:课程ID
问题:
- 行列式 Instructor 不是候选键,而是决定 Room。
- 这违反了 BCNF,因为并非所有决定因素都是候选键。
兼容表(BCNF 中):
要实现 BCNF,请将表分解为两个关系:
- 课程-讲师表:
1 2 3 4 5 |
|
- 教练室桌子:
1 2 3 4 5 |
|
第四范式 (4NF)
定义:
如果满足以下条件,则关系属于 第四范式 (4NF):
- 它采用 Boyce-Codd 范式 (BCNF)(即没有部分、传递或其他异常)。
- 它没有任何多值依赖项。
- 多值依赖(MVD):当表中的一个属性确定多个独立的属性集时,就存在多值依赖。换句话说,如果一个关系包含两个或多个彼此不相关的独立多值属性,则违反了 4NF。
说明:
在 4NF 中,主要目标是消除多值依赖,当记录包含两个或多个不直接相关但由于依赖于同一键而出现在一起的独立属性时,就会发生这种情况。
- 这些类型的依赖关系会导致冗余,因为相同信息的多个副本在行中重复。
- 通过分解关系以删除 MVD,我们消除了冗余并提高了数据库的一致性。
关键概念:
- 在 4NF 中,关系不应具有两个或多个依赖于候选键的多值属性。必须通过适当分解表来消除每个多值依赖关系。
示例:
不合规表(不在 4NF 中):
考虑一个存储有关学生、他们参加的课程以及他们参与的俱乐部的信息的表:
1 2 3 4 |
|
候选键:StudentID
多值依赖:
- StudentID 可以确定一组课程和一组俱乐部,但这些组是相互独立的。
- StudentID → {Courses}(StudentID 和 Courses 之间的多值依赖)
- StudentID → {Clubs}(StudentID 和 Clubs 之间的多值依赖)
该表违反了 4NF,因为 StudentID 独立确定课程和俱乐部。这会导致冗余,因为同一学生 ID 在不同的课程和俱乐部组合中重复多次。
兼容表(在 4NF 中):
为了使表符合4NF,我们必须通过将其分解为两个表来消除多值依赖:
- 学生课程表:
1 2 3 4 5 |
|
- 学生俱乐部桌:
1 2 3 4 |
|
现在,两个多值依赖项是分开处理的:
- 学生-课程表存储学生和他们所修课程之间的关系。
- 学生俱乐部表存储学生和他们所参与的俱乐部之间的关系。
第五范式 (5NF)
定义:
关系采用 第五范式 (5NF),也称为 投影连接范式 (PJNF),如果:
- 它采用第四范式(4NF)(即不存在多值依赖关系)。
- 它不能在不丢失信息的情况下进一步分解,这意味着该关系不包含任何连接依赖或无损连接分解。
- 连接依赖(JD):当一个关系可以分解为两个或多个关系,但当它们重新连接在一起时,不会丢失任何信息,就会发生连接依赖。换句话说,当一个关系可以分为子关系,但原始关系可以在不丢失任何数据的情况下重建时,就存在连接依赖。
说明:
5NF 处理连接依赖,它确保数据以这样的方式分解,即所有信息都可以从分解的部分重建,而不会丢失任何数据。 5NF 中的关系的设计方式是,其所有重要的连接依赖关系都由其候选键隐含。
- 无损连接分解:当一个关系被分解为更小的关系然后重新连接时,原始关系可以完全重建,而不会丢失任何数据。如果一个关系不能在不导致信息丢失的情况下进一步分解,则该关系处于 5NF 状态。
- 非平凡连接依赖性:如果连接依赖性未得到简单满足(即,并非关系中的所有属性都存在于连接依赖性中),则连接依赖性是非平凡的。
简单来说,5NF 关注的是确保不存在因分解不当而导致的冗余。它保证当关系被分解并随后连接回来时,所有原始数据仍然可用,没有任何丢失或歧义。
示例:
不合规表(不在 5NF 中):
考虑一个表,存储有关哪些供应商为不同项目提供哪些零件的信息:
1 2 3 4 |
|
候选键:(供应商、零件、项目)
加入依赖:
上面的关系具有连接依赖性,因为它可以分解为更小的关系而不丢失信息。例如,表可以分解为三个子关系:
- 供应商零件表:
1 2 3 4 |
|
- 供应商-项目表:
1 2 3 4 5 |
|
- 部分项目表:
1 2 3 4 |
|
通过将表分解为这些较小的关系,我们仍然可以通过对这三个较小的关系执行自然连接来重新创建原始表。
但是,由于这种分解是可能的,所以它违反了 5NF。它违反 5NF 的原因是,关于哪个供应商为给定项目提供哪个部件的信息被冗余地存储在多行中。我们多次存储相同的事实,这是不必要的,并且可能会导致不一致。
合规表(5NF 中):
为了实现 5NF,我们分解表,以便在不丢失信息的情况下无法进一步分解关系:
- 供应商-部分-项目表:
1 2 3 4 5 |
|
在这种形式中,关系现在处于 5NF 状态,因为它无法在不丢失数据的情况下进一步分解。该表表示与原始表相同的信息,但以更规范的形式表示,其中每个属性完全依赖于候选键,并且不存在由于分解不当而导致的冗余。
关系设计中的关键概念
- 多值依赖:当一个属性确定多个独立值时。
- 连接依赖:确保在连接期间不会创建虚假元组。
- 依赖关系保留:确保分解后保留所有函数依赖关系。
这份综合指南使您能够掌握关系数据库设计,确保数据库系统高效、一致且无异常。
以上是关系数据库设计:DBMS的详细内容。更多信息请关注PHP中文网其他相关文章!

热门文章

热门文章

热门文章标签

记事本++7.3.1
好用且免费的代码编辑器

SublimeText3汉化版
中文版,非常好用

禅工作室 13.0.1
功能强大的PHP集成开发环境

Dreamweaver CS6
视觉化网页开发工具

SublimeText3 Mac版
神级代码编辑软件(SublimeText3)

在 Linux 中运行 MySQl(有/没有带有 phpmyadmin 的 podman 容器)
