目录
- 前言知识
- 1. 概念
- 1.1 严格定义
- 1.2 通俗理解
- 2. 例题讲解
前言知识
进入主题之前,先补充几个要点知识:
主键(Primary Key):(在数据库设计中,只能有一个主键,但可以由多个列组成(复合主键)。)
- 唯一标识数据库表中每个记录的一列或一组列。
- 在表中必须是唯一的,每个记录都应该有一个不同的主键值。
- 列不允许包含空值(NULL),因为它们用于唯一标识记录。
- 用于建立表之间的关系,例如,用于创建外键关联。
候选键(Candidate Key):
- 表中具有唯一性要求的列或列组合。
- 值也必须是唯一的,就像主键一样。
- 不同于主键,候选键可以包含空值,但其中至少有一个候选键值不能为 NULL。
- 在一个表中,可以有多个候选键,从多个候选键中选择一个作为主键。
候选键通常用于数据库设计的早期阶段,用来识别表中唯一性要求的列。然后,从中选择一个候选键作为主键,通常是选择最适合唯一标识表中记录的那一列或列组合。其他候选键可以用作唯一性约束或索引,以加速查询和确保数据的完整性。
总之,主键是表中用于唯一标识记录的主要标识符,而候选键是具有唯一性要求的列或列组合,可以作为主键的备选项。主键的选择通常依赖于表的设计和业务需求。
- 部分依赖(Partial Dependency):
部分依赖指的是在关系数据库表中的非主键属性部分地依赖于候选键(或主键)的情况。
简而言之,如果一个表的某个非主键属性取决于候选键中的一部分,而不是全部候选键,就称为部分依赖。
这意味着某些属性依赖于表中的一部分键,但不是所有键。
举例来说,考虑一个订单表,其中主键是订单号和产品号。如果订单表中有一个非主键属性是“产品描述”,但这个属性只依赖于“产品号”,而不依赖于“订单号”,那么它就是部分依赖。
这种情况下,数据库设计可能需要进行调整,以消除部分依赖,通常是将属性移到与其完全依赖的关系中。
- 完全依赖(Full Dependency):
完全依赖是指在关系数据库表中的非主键属性完全依赖于候选键(或主键)。
这意味着非主键属性的值取决于表中所有的候选键的值,而不是仅仅一部分。
举例来说,考虑同样的订单表,如果某个非主键属性(如“订单日期”)依赖于主键中的所有属性,即“订单号”和“产品号”,那么它就是完全依赖。
在这种情况下,数据库表的设计是符合第二范式(2NF)的。
总之,部分依赖和完全依赖是与数据库设计中的范式化有关的概念。
数据库设计师通常努力消除部分依赖,以确保数据库表的结构更清晰,减少数据冗余,提高数据一致性和完整性。
这通常涉及到将部分依赖的属性移动到另一个表中,以确保表的非主键属性完全依赖于候选键或主键。
1. 概念
1.1 严格定义
1NF、2NF 和 3NF 是关系数据库设计中的三个重要范式,用于规范化数据库表,以减少冗余数据,提高数据的一致性和完整性。以下是它们的概念:
一、第一范式(1NF – First Normal Form):
第一范式要求数据库表中的每个列都包含不可再分的原子数据,也就是每个单元格中只包含一个值。不应该有多值属性或重复组。
1NF 的要点:
- 每个表中的每一列都必须包含不可再分的原子数据。
- 表中的每一行必须具有唯一的标识符,通常是主键。
- 1NF 确保了表的结构简单和数据的一致性,是数据库设计的第一步。
二、第二范式(2NF – Second Normal Form):
第二范式要求在满足 1NF 的基础上,每列数据都必须完全依赖于表的候选键(Candidate Key)。
这意味着,如果表的候选键包含多列,那么每一列数据都必须与这些列的组合相关,而不是仅与某一列相关。
2NF 的要点:
- 数据表必须满足 1NF。
- 所有非主键列数据必须完全依赖于整个候选键,而不是部分依赖。
- 2NF 的目标是消除部分依赖,以避免数据冗余和维护异常。
三、第三范式(3NF – Third Normal Form):
第三范式要求在满足 2NF 的基础上,消除非主键列之间的传递依赖。这意味着非主键列不能依赖于其他非主键列。
3NF 的要点:
- 数据表必须满足 2NF。
- 每一非主键列都不能传递依赖于其他非主键列。
- 3NF 有助于进一步减少数据冗余,确保数据的完整性,提高数据表的清晰性。
范式的使用有助于设计出更清晰、更容易维护和查询的数据库结构。然而,范式并不是适用于所有情况的绝对规则,有时会导致性能问题。在数据库设计中,需要根据具体需求和性能要求权衡范式和反范式(冗余数据)的使用。
1.2 通俗理解
- 第一范式 (1NF) – 数据的原子性:
类似大型的 Excel 表格,每一行代表一个记录,每一列代表一个属性。
第一范式要求每个单元格(交叉点)中只包含一个值。就像在 Excel 中,每个单元格只能包含一个数字或文本,不能混合多个值。这确保了数据的原子性,使它更容易管理。
- 第二范式 (2NF) – 数据的关联性:
类似数据库表,其中有两列:一个是订单号,另一个是产品名称。
如果一份订单中包含多种产品,那么订单号和产品名称之间存在冗余数据。第二范式要求把这种关联性拆分开,将订单号和产品名称分别存储在不同的表中。这就像将订单和产品的信息分开,以避免重复的信息。
- 第三范式 (3NF) – 数据的传递依赖:
数据库表,其中包含员工信息,包括员工姓名、部门和部门经理。
如果部门经理的信息可以通过部门名直接获取,那么存在传递依赖,因为部门经理信息依赖于部门名,而不是员工。第三范式要求消除这种传递依赖,将部门经理信息从员工表中移除,将它放到一个单独的表中,使数据更清晰,不会有冗余的信息。
总之,三大范式是一种数据库设计的指导原则,帮助我们组织和规范化数据,以减少冗余、提高数据完整性和可维护性。
它们有助于确保数据库表结构清晰,数据不混乱,减少错误和提高数据库的性能。但在实际设计中,有时会根据具体需求和性能考虑,做一些权衡。
2. 例题讲解
以下是一个示例数据库表,以帮助解释这些概念:
假设有一个订单管理系统,其中有两个表:
- 一个是“订单”表(Orders)
- 一个是“产品”表(Products)
这两个表之间有关系,订单中包含了不同产品的信息。
1. 第一范式 (1NF) 示例:
订单表 (Orders):
OrderID | CustomerName | Products |
---|---|---|
1 | John | Product1, Product2 |
2 | Jane | Product3 |
3 | Bob | Product1, Product3 |
在上面的表中,每个单元格包含原子值,没有多值属性,因此符合第一范式(1NF)。
2. 第二范式 (2NF) 示例:
如果我们将产品表(Products)引入,它包含了产品信息,包括产品号(ProductID)、产品名称(ProductName)和产品描述(ProductDescription)。
订单表 (Orders):
OrderID | CustomerName |
---|---|
1 | John |
2 | Jane |
3 | Bob |
产品表 (Products):
ProductID | ProductName | ProductDescription |
---|---|---|
1 | Product1 | Description1 |
2 | Product2 | Description2 |
3 | Product3 | Description3 |
产品表(Products)和订单表(Orders)之间存在关系,通过“产品号”(ProductID)来连接
这符合第二范式(2NF),因为非主键属性(如“产品描述”)依赖于整个候选键(“产品号”)。
3. 第三范式 (3NF) 示例:
如果我们在订单表(Orders)中添加一个新的属性,比如“客户地址”(CustomerAddress):
订单表 (Orders):
OrderID | CustomerName | CustomerAddress |
---|---|---|
1 | John | Address1 |
2 | Jane | Address2 |
3 | Bob | Address1 |
在这种情况下,客户地址(CustomerAddress)依赖于“客户名称”(CustomerName),而不是订单号(OrderID)。
这违反了第三范式(3NF)。为了符合3NF,我们应该将“客户地址”移动到一个独立的客户表,其中“客户名称”是主键,然后在订单表中使用客户名称作为外键来建立关联。