范式3NF简解

本文简要介绍了数据库的3NF范式,强调了3NF在软件系统工程设计中的核心地位。3NF要求消除属性数据冗余,确保每个表的非键值属性在整个数据库中是唯一的。同时,文章提及了数据库设计的其他范式,以及数据库表间的一对一、一对多和多对多关系,并指出在实际设计中,99%遵循范式但允许适当的“反范式”设计。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

范式3NF简解
(作者:张承睿,撰写时间:2019年4月3日)
关系数据库有六种范式:第一范式(1NF)、第二范式(2NF)、第三范式(3NF)、巴德斯克范式(BCNF)、第四范式(4NF)和第五范式(5NF)

 界面层(显示/操作数据)
 逻辑层(处理数据,分布式)
 数据层(传输数据)
 数据库存储(数据库的逻辑设计和物理设计)

设计一个软件的过程:需求分析、原型设计、数据库设计、编码(界面层、逻辑层、数据层、数据库编码)、测试、实施。

N01:架构师(技术总监):需求分析、原型设计、数据库的逻辑设计
N02:项目组长:数据库的逻辑设计 (3个以上完整项目的经验)
N03:高级软件工程师(干活,悲催的码农)

计算机的单元时间是 千分之一毫秒
完成替换 3 5
如果是传统的excel:无法保证数据的完整性

数据库设计(5NF+1)
三范式原则:3NF——软件系统工程设计的核心!!!
3NF设计原则”和“表关系”
1、第一范式(1NF)字段(列、属性):字段原子性。最小的实际意义的文字单元
指数据库表的每一列都是不可分割的基本数据项,属性不可分割,不可二义!
2、第二范式(2NF)表:行的原子性,元组;表,实体的原子性。
数据库表中的每个实例或行必须可以被唯一地区分。非主属性非部分依赖于主关键字。
3、第三范式(3NF):非键值属性在整个数据库中是唯一的。
消除属性数据冗余。例如,存在一个部门信息表,其中每个部门有部门编号(dept_id)、部门名称、部门简介等信息。那么在就不能再将部门名称、部门简介等与部门有关的信息再加入到其他表中。

学生学籍:
A01院系表:院系ID(主键)、院系名称、院系地址、院系编码
A02专业表:专业ID(主键)、院系ID(外键)、专业名称、国家专业编码、
专业简称 学制、培养层次、年级
A03班级表:班级ID、专业ID(外键)、班级名称、学号前缀
1 计算机16-1
2 网络16-1
A04学生表:学生ID、班级ID、学号、姓名、性别、民族、家庭地址、身份号码

“表关系”:数据库中表的关系靠什么建立关系——(外键!)
(1)一:一的关系
例如:一个人对应一个唯一的身份证号,即为一对一的关系。
(2)一:N关系
例如:一个班级对应多名学生,即为一对多关系
(3)多对多关系(在表物理设计中是不存在,多对多其实以n个一对多的组合,即通过一个“关系表”来联系“n个实体表”)
例如:一个学生可以选多门课程,而同一门课程可以被多个学生选修,彼此的对应关系即是多对多关系。
设计数据库 99%遵循范式 允许 “反范式”!!!

数据库设计总结:
每个表必须有一个主键,主键最好是没有任何意义的整型自增性字段;每个表的包含两类字段:键值字段(1个主键,n个外键);外键和普通字段必须是来描述实体本身不可或缺的属性,该属性的组合(元组)构成对该实体数据的唯一性针对性描述。

<think>我们正在讨论数据库设计中的第三范式3NF)。根据用户需求,用户希望理解第三范式3NF)及其应用。根据引用内容,第三范式是数据库设计中的一种规范,用于减少数据冗余,保证数据一致性。 首先,我们需要回顾范式的概念。范式(Normal Form)是数据库设计过程中遵循的规则,目的是为了减少数据冗余,避免数据异常(如插入异常、删除异常、更新异常),并确保数据依赖合理。 第三范式3NF)是在第二范式(2NF)的基础上建立的。因此,理解3NF需要先了解1NF和2NF。 1. **第一范式(1NF)**:要求数据库表的每一列都是不可分割的原子值,即每一列中不能包含多个值或者重复的属性。例如,如果有一个“电话号码”列,其中存储了多个电话号码(如“123-456,789-012”),这就不符合1NF。应该将其拆分为多个行或者单独的列。 2. **第二范式(2NF)**:在满足1NF的基础上,要求非主键属性完全依赖于整个主键,而不是部分依赖于主键(即消除部分依赖)。这通常发生在复合主键的情况下。例如,如果有一个订单明细表,主键是(订单ID,产品ID),而“产品名称”只依赖于“产品ID”,而不依赖于“订单ID”,那么“产品名称”就是部分依赖于主键,不符合2NF。解决方法是把产品相关信息拆分到单独的产品表中。 3. **第三范式3NF)**:在满足2NF的基础上,要求非主键属性之间不能有传递依赖(即消除传递依赖)。也就是说,非主键属性必须直接依赖于主键,而不能依赖于其他非主键属性。例如,假设有一个学生表,包含学号(主键)、姓名、学院、学院电话。其中,“学院电话”依赖于“学院”,而“学院”又依赖于“学号”,那么“学院电话”就通过“学院”传递依赖于学号。这不符合3NF,因为“学院电话”应该直接与学院相关,而不是与学生学号直接相关。解决方法是把学院相关信息拆分到单独的学院表中。 **第三范式的定义**: 一个关系模式R属于第三范式3NF),当且仅当: - R满足2NF。 - 对于R中的每一个非平凡函数依赖$X \to Y$(其中Y不包含于X),要么X是超键,要么Y是主属性(即Y是候选键的一部分)[^1]。 另一种等价的定义是:不存在非主属性对候选键的传递依赖。 **应用示例**: 假设我们有一个学生选课系统的数据库,最初设计了一个表`StudentCourse`,包含以下字段: - 学号(StudentID) - 姓名(Name) - 系名(Department) - 系主任(Dean) - 课程号(CourseID) - 课程名称(CourseName) - 成绩(Grade) 这个表存在以下问题: 1. 数据冗余:同一个学生选择多门课程,那么学生的姓名、系名、系主任会重复出现;同一门课程被多个学生选择,课程名称也会重复。 2. 更新异常:如果某个系更换了系主任,那么需要更新该系所有学生的记录,如果有遗漏就会导致数据不一致。 3. 插入异常:如果某个系还没有学生,那么就无法添加该系的信息。 4. 删除异常:如果某个系的学生全部毕业,删除这些学生记录时,系的信息也会被删除。 现在,我们按照3NF进行分解: 步骤1:满足1NF(每个字段都是原子的,这里假设都是原子值)。 步骤2:满足2NF。首先确定候选键。在这个表中,候选键应该是(学号,课程号),因为一个学生可以选择多门课程,一门课程可以被多个学生选择,所以用(学号,课程号)唯一确定一条记录。非主键属性包括:姓名、系名、系主任、课程名称、成绩。 检查部分依赖: - 姓名、系名、系主任只依赖于学号(即部分依赖于候选键中的学号,而不依赖于课程号),所以不符合2NF。 - 课程名称依赖于课程号(部分依赖于候选键中的课程号),不符合2NF。 - 成绩依赖于(学号,课程号)完全,符合2NF。 因此,我们需要分解: - 将学生信息提取出来:新建表`Student`,包含(学号,姓名,系名,系主任)。这里主键是学号。 - 将课程信息提取出来:新建表`Course`,包含(课程号,课程名称)。主键是课程号。 - 剩下的成绩信息:保留在`StudentCourse`表中,包含(学号,课程号,成绩),主键是(学号,课程号),外键是学号(引用`Student`表)和课程号(引用`Course`表)。 现在,我们检查每个表是否满足2NF: - `Student`表:主键是学号,非主键属性(姓名、系名、系主任)都完全依赖于学号(整个主键),所以满足2NF。 - `Course`表:主键是课程号,非主键属性课程名称完全依赖于课程号,满足2NF。 - `StudentCourse`表:主键(学号,课程号),非主键属性成绩完全依赖于主键,满足2NF。 步骤3:满足3NF。检查每个表是否存在传递依赖。 - `Student`表:学号→系名,系名→系主任。因此,系主任传递依赖于学号(即学号→系名→系主任)。所以这里存在传递依赖,不符合3NF。 - `Course`表:只有两个属性,不存在传递依赖。 - `StudentCourse`表:只有三个属性,也不存在传递依赖。 因此,我们需要进一步分解`Student`表: - 将系的信息提取出来:新建表`Department`,包含(系名,系主任),主键是系名。 - 修改`Student`表,只包含(学号,姓名,系名),其中系名作为外键引用`Department`表的系名。 现在,所有表都满足3NF: - `Student`表:学号(主键),姓名,系名(外键) - `Department`表:系名(主键),系主任 - `Course`表:课程号(主键),课程名称 - `StudentCourse`表:学号(外键),课程号(外键),成绩 这样,数据冗余减少了,更新异常等问题也得到了解决。 **总结第三范式的应用**: - 设计数据库时,首先确保满足1NF和2NF。 - 检查是否存在传递依赖,即非主键属性是否依赖于其他非主键属性(而不是直接依赖于主键)。 - 通过分解表,将存在传递依赖的属性拆分到新的表中,并使用外键关联。 通过以上步骤,我们可以设计出符合3NF的数据库结构,从而减少数据冗余,避免数据操作异常,保证数据一致性。 [^1]:【数据库】第一范式(1NF),第二范式(2NF),第三范式(3NF),BCNF和第四范式(4NF)详解 [^2]:数据库三大范式(3NF)详解 §§相关问题§§ 1. 第三范式3NF)与巴斯-科德范式(BCNF)有什么区别? 2. 在实际数据库设计中,是否总是需要遵循第三范式3. 如何判断一个数据库设计是否满足第三范式? 4. 第三范式在哪些场景下可能不适用?</think>### 第三范式3NF)的理解与应用 第三范式3NF)是数据库设计中的核心规范,用于消除数据冗余和操作异常(如插入、删除、更新异常)。它建立在第一范式(1NF)和第二范式(2NF)的基础上,核心要求是**消除非主属性对主键的传递依赖**。 --- #### 一、核心概念解析 1. **前提条件**: - **1NF**:表中所有字段都是原子值(不可再分)。 > *示例*:`用户地址`字段若存储“北京市海淀区#中关村”,需拆分为`省`、`市`、`详细地址`。 - **2NF**:在1NF基础上,消除**非主属性对主键的部分依赖**(针对复合主键)。 > *示例*:订单明细表(订单ID, 产品ID, 产品名称)中,`产品名称`仅依赖`产品ID`而非完整主键,需拆分为“订单明细表”和“产品表” [^1]。 2. **3NF的核心要求**: - 所有**非主属性**必须**直接依赖于主键**,不能通过其他非主属性间接依赖(即消除传递依赖)。 - 形式化定义:若存在函数依赖 $A \to B$ 和 $B \to C$,则 $A \to C$ 是传递依赖,需拆分表 [^2]。 --- #### 二、违反3NF的示例与修正 假设有一个`学生信息表`: | **学号**(主键) | 姓名 | 学院 | 学院电话 | |----------------|------|------|----------| | S001 | 张三 | 计算机学院 | 010-1234 | **问题分析**: - 主键:`学号` - 非主属性:`学院电话` 依赖于 `学院`,而 `学院` 依赖于 `学号`,形成传递依赖(学号 → 学院 → 学院电话)。 - **后果**: - 冗余:同一学院的学生重复存储学院电话。 - 更新异常:修改学院电话需更新多条记录。 - 删除异常:删除所有学生可能导致学院信息丢失。 **修正步骤(应用3NF)**: 1. 拆分原表为两个表: - **学生表**:`学号`(主键),`姓名`,`学院`(外键) - **学院表**:`学院`(主键),`学院电话` ```sql CREATE TABLE 学院表 ( 学院 VARCHAR(50) PRIMARY KEY, 学院电话 VARCHAR(20) ); CREATE TABLE 学生表 ( 学号 VARCHAR(10) PRIMARY KEY, 姓名 VARCHAR(50), 学院 VARCHAR(50), FOREIGN KEY (学院) REFERENCES 学院表(学院) ); ``` 2. **修正后关系**: - 非主属性(如`学院电话`)直接依赖主键(`学院`),消除了传递依赖。 --- #### 三、3NF的实际应用场景 1. **减少数据冗余**: - 例如电商系统中,将`订单表`拆分为“订单主表”(订单ID, 用户ID)和“订单详情表”(商品ID, 数量),避免重复存储用户/商品信息。 2. **保证数据一致性**: - 学院电话仅在`学院表`中存储一次,所有学生通过外键引用,避免更新不一致。 3. **优化查询效率**: - 小表更易索引,如按学院电话查询时只需扫描`学院表`而非全量学生数据。 --- #### 四、3NF的局限性 - **性能权衡**:过度规范化可能导致多表连接(JOIN)操作增加,影响查询性能。 > *解决方案*:对高频查询的表适当反范式化(如冗余部分字段)[^2]。 - **不解决所有依赖**: - 3NF不处理主属性间的依赖(需BCNF解决),如多候选键导致的复杂依赖。 --- #### 五、总结 - **3NF目标**:通过消除传递依赖,确保非主属性直接依赖主键,实现数据高内聚、低冗余。 - **设计步骤**: 1. 满足1NF → 2NF3NF。 2. 识别传递依赖:检查是否存在链式依赖($A \to B \to C$)。 3. 拆分表,使非主属性直接关联主键。 > 实际设计中需平衡范式与性能,通常在OLTP系统(如交易系统)优先遵循3NF,OLAP系统(如数据分析)允许反范式优化 [^1][^2]。 [^1]:【数据库】第一范式(1NF),第二范式(2NF),第三范式(3NF),BCNF和第四范式(4NF)详解 [^2]: 数据库三大范式(3NF)详解 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值