浅谈数据库三大范式

为什么要遵循范式?

通过应用范式化设计,可以提高数据库的结构清晰性、数据一致性和操作效率。然而,范式化也可能导致查询复杂性增加和数据冗余的增加。因此,在实际应用中,需要根据具体需求和性能要求进行适当的范式化设计。

什么是数据库三大范式?

数据库的范式,是一种规范化的设计方法,主要用于优化数据库的结构和操作效率。范式可以分为多个级别,其中最常用的是三种范式,即第一范式(1NF)、第二范式(2NF)和第三范式(3NF)。

第一范式(1NF)要求数据库中的每个列必须是原子性的,即不可再分解。也就是说,每个列中的每个值都必须是唯一的,并且不可再细分为更小的数据。

第二范式(2NF)在满足第一范式的基础上,要求数据库中的每个非主键列必须完全依赖于主键列。换句话说,每个非主键列的值必须与主键关联,并且不能依赖其他非主键列。

第三范式(3NF)在满足第二范式的基础上,要求数据库中的每个非主键列都必须直接依赖于主键列,而不能间接依赖于其他非主键列。也就是说,任何非主键列的值都不能通过其他非主键列推导出来。

最佳实践

第一范式

如何将一个非规范化的表转换为满足第一范式(1NF)的形式

假设有如下非规范化的表,记录了某个公司的员工信息:
在这里插入图片描述

在上述表结构中,每个记录中有多个属性(姓名、职位、工资),这违反了第一范式的要求,因为每个列必须是原子性的。

为了满足第一范式,我们可以将上述表进行拆分,得到两个规范化的表:

表1:员工信息(Employee)

在这里插入图片描述
表2:职位信息(Position)
在这里插入图片描述
现在,每个表都满足了第一范式的要求,每个列都是原子性的,没有多个值。这样的数据结构更加规范和易于管理。

举一个反例,展示一个不符合第一范式(1NF)以及如何拆分正确使用第一范式

假设有如下表,记录了某个班级的学生信息:

在这里插入图片描述
在上述表结构中,一列中存储了多个学生的姓名,违反了第一范式的要求,因为每个列必须是原子性的。

为了满足第一范式,我们可以将上述表进行拆分,得到两个规范化的表:

表1:班级信息(Class)

在这里插入图片描述

表2:学生信息(Student)

在这里插入图片描述
表3:班级与学生关联信息(Class_Student)
在这里插入图片描述
通过拆分表并引入关联表,每个表都满足了第一范式的要求,每个列都是原子性的。这样的数据结构更加规范和易于管理。

第二范式

第二范式(2NF)要求一个表中的所有列都必须完全依赖于表的主键。也就是说,如果一个表有多个候选键,则每个非主键列必须完全依赖于每个候选键。

正例:
考虑一个订单系统。假设我们有如下订单表:

Order (order_id, customer_id, customer_name, product_id, product_name, quantity, price)
在这里插入图片描述

在这个表中,order_id 是主键,而其他列并不完全依赖于主键。例如,customer_name和product_name 列依赖于 customer_id 和 product_id 列。为了满足第二范式,我们可以将表拆分成多个表,如下所示:

Order (order_id, customer_id, product_id, quantity, price)
在这里插入图片描述

Customer (customer_id, customer_name)
在这里插入图片描述

Product (product_id, product_name)

在这里插入图片描述

现在每个表都符合第二范式的要求:主键和非主键列之间的关系被明确定义了。

反例:
假设有如下图书馆图书借阅记录的表:

Book_loans (Book_id, Title, Author, Borrower_id, Borrower_name, Checkout_date, Due_date)
在这里插入图片描述

在这个表中,Book_id 和 Borrower_id 是联合主键。但是 Title 和 Author 列并不完全依赖于 Book_id,而 Borrower_name 列也并不完全依赖于 Borrower_id。因此,这个表不符合第二范式的要求。

为了满足第二范式,我们可以将表拆分成多个表,如下所示:

Books (Book_id, Title, Author)
在这里插入图片描述

Borrowers (Borrower_id, Borrower_name)
在这里插入图片描述

Loans (Book_id, Borrower_id, Checkout_date, Due_date)
在这里插入图片描述

现在每个表都符合第二范式的要求:主键和非主键列之间的关系被明确定义了。

第三范式

第三范式要求一个表中的每一列必须都与主键直接相关,而不能依赖于其他非主键列。也就是说,一个表中不能存在传递依赖关系。

正例
考虑一个学校课程表。假设我们有如下表:

Course_schedule (Course_code, Course_name, Department, Instructor, Instructor_office)
在这里插入图片描述

在这个表中,Course_code 是主键。但是 Department 列依赖于 Course_code 和 Instructor 列,而 Instructor_office 列依赖于 Instructor 列。因此,这个表不符合第三范式的要求。

为了满足第三范式,我们可以将表拆分成多个表,如下所示:

Course (Course_code, Course_name, Instructor)
在这里插入图片描述

Department (Course_code, Instructor, Department)
在这里插入图片描述

Instructor_office (Instructor, Instructor_office)
在这里插入图片描述

现在每个表都符合第三范式的要求:每一列都与主键直接相关。

反例:
假设有如下订单系统。假设我们有如下订单表:

Order (order_id, customer_id, customer_name, customer_address, product_id, product_name, price, order_date)
在这里插入图片描述

在这个表中,order_id 是主键。但是 customer_name 和 customer_address 列依赖于 customer_id 列。因此,这个表不符合第三范式的要求。

为了满足第三范式,我们可以将表拆分成多个表,如下所示:

Order (order_id, customer_id, product_id, price, order_date)
在这里插入图片描述

Customer (customer_id, customer_name, customer_address)
在这里插入图片描述

现在每个表都符合第三范式的要求:每一列都与主键直接相关。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值