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