数据库设计三范式 作者:马育民 • 2020-05-16 09:35 • 阅读:10147 # 第一范式 表中的字段不可再分 如下图: `地区`、`户型` 都 **可再分**,而且分开后更加便于 **查询** [](https://www.malaoshi.top/upload/0/0/1EF3t6EwB8JD.png) ### 如何满足范式 需要拆分字段 ### 好处 - 数据一致性:避免同一个字段中存储多个含义不同的信息 - 查询方便性:如果字段可再分,SQL 就无法有效查询和处理 - 更新安全性:减少更新异常,避免部分数据被遗漏或错误修改 ### 缺点 下图是供应商和提供零件的信息: - Sno是主键 - Sname是供应商名 - Status是状态 - City是城市 - Pno:零件编号 - Qty:零件数量??? 关系: - Sno能确定Sname、Status - Status能确定City - Sno和pno能确定Qty [](https://www.malaoshi.top/upload/0/0/1GW12msC2LGg.png) 从上图可以看出,每个属性都不可再分,满足范式一 但存在下面4个问题: - 冗余度大。例如,每个供应者的 Sno、Sname、Status、City要与其供应的零件的种类一样多。 - 引起修改操作的不一致性。例如,供应者S1从“天津”搬到“上海”,若稍不注意,就会使一些数据被修改,另一些数据没有被修改,导致数据修改的不一致性。 - 插入异常。主健为 Sno、Pno,主健不能为null。但是,当某个供应者的某些信息未提供时(如Pno),则不能进行插入操作,否则报错 - 删除异常。若供应商 S4的P2零件销售完了,并且以后不再销售P2零件,那么应删除该条记录。这样,在基本关系FIRST找不到S4,而 S4又是客观存在的。 正因为上述4个原因,所以要对模式进行分解,并引入了范式二。 # 第二范式 表中的每一列都和主键相关,而不能只与主键的某一部分相关 **理解:**一个表中只能保存一个实体的数据 如下图: - 学号、课程号是主键 - 成绩与学号、课程号相关,符合范式二 - 学分与课程号相关,与学号不相关,不符合范式二 [](https://www.malaoshi.top/upload/0/0/1GW12nkNBLJv.png) **解决:**拆分成两个表 - 表1:有学号、课程号、成绩 - 表2:有课程号、学分 ### 供应商例子 上图供应商例子中,主健为 Sno、Pno,但Sname、Status 与 Sno 相关,与 Pno 不相关,这就违背范式二 ### 如何满足范式 需要拆分多个表: - FIRST1(Sno,Sname,Status,City),Sname,Status,City 与 Sno 相关,符合范式二 - FIRST2(Sno,Pno,Qty),Qty 与 Sno、Pno 相关,符合范式二 # 第三范式 每一列数据都和主键 **直接相关**,而不能间接相关 如图: - 学号是主键 - 姓名、系号与学号直接相关 - 系名、系位置与系号直接相关,与学号 **间接相关**,不符合范式三 [](https://www.malaoshi.top/upload/0/0/1GW12nmHHMkB.png) **解决:**拆分成两个表 - 表1:学号、姓名、系号 - 表2:系号、系名、系位置 ### 供应商例子 FIRST1 不满足范式三,因为 `Status` 与 `Sno` 相关,`City` 与 `Status` 相关,存在着 `City` 与 `Sno` 间接相关 ### 如何满足范式 需要拆分表,将FIRST1拆为: - FIRST11 (Sno, Sname, Status),Sname、Status 与 Sno 直接相关 - FIRST12 (Status, City),City 与 Status 直接相关 原文出处:http://www.malaoshi.top/show_1EF5X1BLw7Wz.html