数据库的三范式详细解释

1.定义

三范式是数据库的规范化的内容,所谓的数据库三范式通俗的讲就是设计数据库表所应该遵守的一套规范,如果不遵守就会造成设计的数据库不规范,出现数据库字段冗余,数据的查询,插入等操作等问题。

注意:数据库不仅仅只有三范式(1NF/2NF/3NF),还有BCNF、4NF、5NF…,不过在实际的数据库设计时,遵守前三个范式就足够了。再向下就会造成设计的数据库产生过多不必要的约束。

2.数据库的三范式内容及详解

第一范式:数据库表中的每一列都不可再分,也就是原子性

解释:如下表所示,可以看到,列部门岗位是不满足原子性的要求的。所谓原子就是最小的。不能再把它进行划分了。在部门岗位中,是可以进行划分为部门和岗位的。

在这里插入图片描述
修改后的表:

在这里插入图片描述

第二范式:在满足第一范式基础上要求每个字段都和主键完整相关,而不是仅和主键部分相关(主要针对联合主键而言)

第二范式的另一种表述方式是:两张表要通过外键关联,不保存冗余字段。

注意:如果不是联合主键(两个字段共同充当表的主键),不存在不遵守第二范式的问题。

解释:如下表:
在这里插入图片描述

直接看这个表可能第一感觉就是没毛病。但是当一个表中出现联合主键时,我们就需要进行详细的分析了。
“订单详情表”使用“订单编号”和“产品编号”作为联合主键。此时“产品价格”、 “产品数量”都和联合主键整体相关,但 “订单金额”和“下单时间” 只和联合主键中的“订单编号”相关,和“产品编号”无关。所以只关联了主键中的部分字段,不满足第二范式。

修改表如下:把“订单金额”和“下单时间”移到订单表就符合第二范式了。
在这里插入图片描述

第三范式:表中的非主键字段和主键字段直接相关,不允许间接相关

在这里插入图片描述
上面表中的“部门名称”和“员工编号”的关系是“员工编号”→“部门编号” →“部门名称”,不是直接相关。此时会带来下列问题:
1.数据冗余:“部门名称”多次重复出现。
2.插入异常:组建一个新部门时没有员工信息,也就无法单独插入部门信息。就算强行插入部门信息,员工表中没有员工信息的记录同样是非法记录。
3. 删除异常:删除员工信息会连带删除部门信息导致部门信息意外丢失。
4.更新异常:哪怕只修改一个部门的名称也要更新多条员工记录。

正确的方式:把上表拆分成两张表,以外键形式关联

在这里插入图片描述

3.实际开发中注意事项

三大范式是设计数据库表结构的规则约束,但是在实际开发中允许局部变通。

如何变通呢?

比如为了快速查询到关联数据可能会允许冗余字段的存在。例如在员工表 中存储部门名称虽然违背第三范式,但是免去了对部门表的关联查询。

根据业务功能设计数据库表

1).看得见的字段
能够从需求文档或原型页面上直接看到的数据都需要设计对应的数据库表、字段来存储。例如设计一个登录界面的功能。设计表需要有账号、密码。

2).看不见的字段
除了能够直接从需求文档中看到的字段,实际开发中往往还会包含一 些其他字段来保存其他相关数据。 例如主键、创建账户时间。

3).冗余字段
为了避免建表时考虑不周有所遗漏,到后期再修改表结构非常麻烦, 所以有时会设置一些额外的冗余字段备用。

### 数据库三大范式详解 数据库范式是数据库设计中用于减少数据冗余和提高数据一致性的规则集合。以下是第一范式、第二范式和第三范式详细解释。 #### 第一范式(1NF) 第一范式要求数据库表中的每一列都必须是不可再分的基本数据项,即表中的每个字段值都是单一值,而不是一组值或一个列表。这意味着表中的每一行和每一列的交叉点上只能有一个值[^1]。 例如,如果有一个学生表,其中“课程”字段包含多个课程名称,则不符合第一范式。应该将这些课程拆分为单独的记录。 ```sql -- 不符合1NF的表结构 CREATE TABLE Students ( StudentID INT, Name VARCHAR(50), Courses VARCHAR(255) -- 包含多个课程名称 ); -- 符合1NF的表结构 CREATE TABLE Students ( StudentID INT, Name VARCHAR(50) ); CREATE TABLE StudentCourses ( StudentID INT, CourseName VARCHAR(50) ); ``` #### 第二范式(2NF) 第二范式建立在第一范式的基础上,要求消除部分依赖。也就是说,非主键字段必须完全依赖于主键,而不能只依赖于主键的一部分。对于具有联合主键的表,所有非主键字段必须依赖于整个联合主键,而不是其中的某一部分[^3]。 例如,假设有一个订单明细表,其中订单号和产品ID共同组成联合主键。如果某个字段(如客户姓名)只依赖于订单号而不依赖于产品ID,则该表不符合第二范式。 ```sql -- 不符合2NF的表结构 CREATE TABLE OrderDetails ( OrderID INT, ProductID INT, CustomerName VARCHAR(50), -- 只依赖于OrderID Quantity INT, PRIMARY KEY (OrderID, ProductID) ); -- 符合2NF的表结构 CREATE TABLE Orders ( OrderID INT, CustomerName VARCHAR(50), PRIMARY KEY (OrderID) ); CREATE TABLE OrderProducts ( OrderID INT, ProductID INT, Quantity INT, PRIMARY KEY (OrderID, ProductID) ); ``` #### 第三范式(3NF) 第三范式建立在第二范式的基础上,要求消除传递依赖。也就是说,非主键字段不能依赖于其他非主键字段[^3]。如果某个字段可以通过另一个非主键字段间接推导出来,则需要将其分离到独立的表中。 例如,假设有一个员工表,其中“部门名称”字段可以通过“部门ID”推导出来,则该表不符合第三范式。 ```sql -- 不符合3NF的表结构 CREATE TABLE Employees ( EmployeeID INT, Name VARCHAR(50), DepartmentID INT, DepartmentName VARCHAR(50), -- 依赖于DepartmentID PRIMARY KEY (EmployeeID) ); -- 符合3NF的表结构 CREATE TABLE Departments ( DepartmentID INT, DepartmentName VARCHAR(50), PRIMARY KEY (DepartmentID) ); CREATE TABLE Employees ( EmployeeID INT, Name VARCHAR(50), DepartmentID INT, PRIMARY KEY (EmployeeID), FOREIGN KEY (DepartmentID) REFERENCES Departments(DepartmentID) ); ``` #### 实际应用中的权衡 虽然遵循范式可以减少数据冗余并提高一致性,但在实际应用中,有时需要根据业务需求进行反范式设计以优化查询性能[^2]。例如,在高并发读取场景下,可以通过增加冗余字段来避免复杂的关联查询,从而提升读取效率。 ---
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值