[学习笔记] 数据库设计三大范式与 BCNF,学习笔记

简介: [学习笔记] 数据库设计三大范式与 BCNF,学习笔记

参考:

1. 范式间的区别

http://www.cnblogs.com/winlinglin/archive/2008/11/19/1336337.html

2. 数据库范式 1NF 2NF 3NF BCNF

http://dev.firnow.com/course/7_databases/sql/sqlServer/20090502/166234.html

3. 萨师煊 & 王珊《数据库系统概论》(第三版)

概念:

(1) 实体(entity):就是实际应用中要用数据描述的事物,一般是名词。

(2) 字段(fields):就是一项数据,也就是我们平常所说的 “列”。

(3) 记录(record):一个实体的一个实例所特有的相关数据项的集合,也就是我们平常所说的 “行”。

(4) 键(key):可唯一标识一条记录的一个字段或字段集,有时翻译为 “码”。

(5) 主键(primary key):用于唯一标识一个表中的一条记录的键。每个主键应该具有下列特征:

1.  唯一的。

2. 最小 的(尽量选择最少键的组合)。

3. 非空。

4. 不可更新的(不能随时更改)

(6) 外键(foreign keys):对连接父表和子表的相关记录的主键字段的复制。

(7) 依赖表(dependent table):也称为弱实体(weak entity)是需要用父表标识的子表。

(8) 关联表(associative table):是多对多关系中两个父表的子表。

(9) 实体完整性:每个表必须有一个有效的主 键。

(10) 参照完整性:没有不相匹配的外键值。

名词解释:

函数依赖:

通俗描述:

描述一个学生的关系,可以有学号 (SNO), 姓名 (SNAME), 系名 (SDEPT) 等几个属性。由于一个学号只对应一个学生,一个学生只在一个系学习。因此当学号确定之后,姓名和该学生所在系的值也就唯一被确定了,就像自变量 x 确定之后,相应的函数值 f (x) 也就唯一地被确定了一样,称 SNO 函数决定 SNAME 和 SDEPT,或者说 SNAME,SDEPT 函数依赖于 SNO,记为:SNO -> SNAME, SNO -> SDEPT.

严格定义:

设 R (U) 是属性集 U 上的关系模式。X,Y 是 U 的子集。若对于 R (U) 的任意一个可能的关系 r,r 中不可能存在两个元组在 X 上的属性值相等,而在 Y 上的属性值不相等,则称 X 函数确定 Y 或者 Y 函数依赖于 X。记为 X->Y。

(如果不知道 “关系”、“属性集” 等定义,自己看大学教材去。这里的定义摘自萨师煊 & 王珊《数据库系统概论》第三版)

完全函数依赖:

在 R (U) 中,如果 Y 函数依赖于 X, 并且对于 X 的任何一个真子集 X',都有 Y 不函数依赖于 X', 则称 Y 对 X 完全函数依赖。否则称 Y 对 X 部分函数依赖。

举个例子就明白了。假设一个学生有几个属性

SNO 学号

SNAME 姓名

SDEPT 系

SAGE 年龄

CNO 班级号

G 成绩

对于 (SNO,SNAME,SDEPT,SAGE,CNO,G) 来说,G 完全依赖于 (SNO, CNO), 因为 (SNO,CNO) 可以决定 G,而 SNO 和 CNO 都不能单独决定 G。

而 SAGE 部分函数依赖于 (SNO,CNO), 因为 (SNO,CNO) 可以决定 SAGE,而单独的 SNO 也可以决定 SAGE。

传递函数依赖:

在 R (U) 中,如果 X->Y, Y->Z, 则称 Z 对 X 传递函数依赖。

候选键

(又称候选码,候选关键字,码 ,candidate key):

设 K 是一个 R (U) 中的属性或属性集合 (注意可以是属性集合,也即多个属性的组合),若 K 完全函数确定 U,则 K 为 R 的候选键 (Candidate key);

通俗地说就是,能够确定全部属性的某个属性或某组属性,称为候选键。若候选键多于一个,则选定其中一个作为主键。

主属性:

包含在任何一个候选键中的属性,叫做主属性 (Prime attribute), 不包含在任何候选键中的属性称为非主属性或非键属性或非关键字段。

例子:

在 (SNO, CNO, G) 中,SNO 和 CNO 这俩合起来就是一个候选键,因为每个元组只要确定了 SNO 和 CNO,则其它所有属性都可以根据 SNO 和 CNO 来确定。而 SNO 和 CNO 就都是 “主属性”,G 是 “非主属性”。由于此例中只有一个候选键,于是只能选择 (SNO, CNO) 作为主键。

在 (SNO,SDEPT, SNAME) 中,SNO 是一个候选键,因为只要 SNO 确定了,其它所有属性也都确定了,如果保证没有重名的话,则 SNAME 也是一个候选键,于是可以选 SNO 或者 SNAME 之一作为候选键。如果不能保证没有重名,就不能把 SNAME 当成候选键,于是就只有 SNO 能够做主键。

范式:

第一范式不多说了

指数据库表的每一列都是不可分割的基本数据项在任何一个关系数据库中,第一范式(1NF)是对关系模式的基本要求,不满足第一范式(1NF)的数据库就不是关系数据库。

第二范式:

数据库表中不存在非关键字段对任一候选键的部分函数依赖,也即所有非关键字 段都完全依赖于任意一组候选关键字。

2NF 的违例只会出现在候选键由超过一个字段构成的表中,因为对单关键字字段不存在部分依赖问题。

例子:(学号,姓名,年龄,课程名称,成绩,学分)

候选键只有一个,就是 (姓名,课程名称),则主键就是 (姓名,课程名称)

存在如下决定关系:

1:(学号,课程名称) → (姓名,年龄,成绩,学分)

2:(课程名称) → (学分)

3:(学号) → (姓名,年龄)

其中,姓名、年龄、学分是部分依赖于主键的,而成绩是完全依赖于主键的,存在部分依赖关系,所以不满足第二范式。

这会造成如下问题

(1) 数据冗余:

同一门课程由 n 个学生选修,"学分" 就重复 n-1 次;同一个学生选修了 m 门课程,姓名和年龄就重复了 m-1 次。

(2) 更新异常:

若调整了某门课程的学分,数据表中所有行的 "学分" 值都要更新,否则会出现同一门课程学分不同的情况。

(3) 插入异常:

假设要开设一门新的课程,暂时还没有人选修。这样,由于还没有 "学号" 关键字,课程名称和学分也无法记录入数据 库。

(4) 删除异常:

假设一批学生已经完成课程的选修,这些选修记录就应该从数据库表中删除。但是,与此同 时,课程名称和学分信息也被删除了。很显然,这也会导致插入异常。

问题就在于存在非主属性对主键的部分依赖

解决办法:把原表 (学号,姓名,年龄,课程名称,成绩,学分) 分成三个表:

学生:Student (学号,姓名,年龄);

课程:Course (课程名称,学分);

选课关 系:SelectCourse (学号,课程名称,成绩)。

第三范式:

在第二范式的基础上,数据表中如果不存在非关键字段对任一候选关键字段的传递函数依赖则符合第三范式

出现传递依赖 A->B->C,即主键 A 可以确定出某一非关键字段 B,而 B 又可以确定出 C,这意味着 C 依赖于一个非关键字段 B。因此第三范式又可描述为:表中不存在可以确定其他非关键字的非键字段

例子:表:(学号,姓名,年龄,所在学院,学院地点,学院电话)

该表中候选字段只有 “学号”,于是 “学号” 做主键。由于主键是单一属性,所以不存在非主属性对主键的部分函数依赖的问题,所以必然满足第二范式。但是存在如下传递依赖

(学号) → (所在学院) → (学院地点,学院电话)

学院地点和学院电话传递依赖于学号,而学院地点和学院电话都是非关键字段,即表中出现了 “某一非关键字段可以确定出其它非关键字段” 的情况,于是违反了第三范式。

解决办法:

把原表分成两个表:

学生:(学号,姓名,年龄,所在学院);

学院:(学院,地点,电话)。

BCNF:

BCNF 意味着在关系模式中每一个决定因素都包含候选键,也就是说,只要属性或属性组 A 能够决定任何一个属性 B,则 A 的子集中必须有候选键。BCNF 范式排除了任何属性 (不光是非主属性,2NF 和 3NF 所限制的都是非主属性) 对候选键的传递依赖与部分依赖。

例子:

例子二:

假设仓库管理关系表为 StorehouseManage (仓库 ID, 存储物品 ID, 管理员 ID, 数量),且有一个管理员只在一个仓库工作;一个仓库可以存储多种物品。这个数据库表中存在如下决定关系:

(仓库 ID, 存储物品 ID) →(管理员 ID, 数量)

(管理员 ID, 存储物品 ID) → (仓库 ID, 数量)

所以,(仓库 ID, 存储物品 ID) 和 (管理员 ID, 存储物品 ID) 都是 StorehouseManage 的候选关键字,表中的唯一非关键字段为数量,它是符合第三范式的。但是,由于存在如下决定关系:

(仓库 ID) → (管理员 ID)

(管理员 ID) → (仓库 ID)

仓库 I 是决定因素,但仓库 ID 不包含候选键 (candidate key, 也就是候选码,简称码)。

同样的,管理员 ID 也是决定因素,但不包含候选键。

所以该表不满足 BCNF。

3NF 和 BCNF 是在函数依赖的条件下对模式分解所能达到的最大程度。一个模式中的关系模式如果都属于 BCNF,那么在函数依赖范围内,它已经实现了彻底的分离,已消除了插入和删除的异常。3NF 的 “不彻底” 性表现在可能存在主属性对键的部分依赖和传递依赖。

相关文章
|
27天前
|
存储 SQL 关系型数据库
Mysql学习笔记(二):数据库命令行代码总结
这篇文章是关于MySQL数据库命令行操作的总结,包括登录、退出、查看时间与版本、数据库和数据表的基本操作(如创建、删除、查看)、数据的增删改查等。它还涉及了如何通过SQL语句进行条件查询、模糊查询、范围查询和限制查询,以及如何进行表结构的修改。这些内容对于初学者来说非常实用,是学习MySQL数据库管理的基础。
104 6
|
27天前
|
SQL Ubuntu 关系型数据库
Mysql学习笔记(一):数据库详细介绍以及Navicat简单使用
本文为MySQL学习笔记,介绍了数据库的基本概念,包括行、列、主键等,并解释了C/S和B/S架构以及SQL语言的分类。接着,指导如何在Windows和Ubuntu系统上安装MySQL,并提供了启动、停止和重启服务的命令。文章还涵盖了Navicat的使用,包括安装、登录和新建表格等步骤。最后,介绍了MySQL中的数据类型和字段约束,如主键、外键、非空和唯一等。
62 3
Mysql学习笔记(一):数据库详细介绍以及Navicat简单使用
|
3天前
|
存储 数据库
数据库设计三范式
数据库设计三范式
8 0
|
2月前
|
SQL 关系型数据库 MySQL
php学习笔记-连接操作mysq数据库(基础)-day08
本文介绍了PHP中连接操作MySQL数据库的常用函数,包括连接服务器、设置字符集、关闭连接、选择数据库、结果集释放、获取影响行数以及遍历结果集等操作。通过书籍查询的实例演示了如何使用这些函数进行数据库操作,并提供了一个PHP操纵MySQL数据库的模板。
php学习笔记-连接操作mysq数据库(基础)-day08
|
3月前
|
SQL druid Java
Java数据库部分(MySQL+JDBC)(二、JDBC超详细学习笔记)(下)
Java数据库部分(MySQL+JDBC)(二、JDBC超详细学习笔记)
53 3
Java数据库部分(MySQL+JDBC)(二、JDBC超详细学习笔记)(下)
|
3月前
|
SQL Java 关系型数据库
Java数据库部分(MySQL+JDBC)(二、JDBC超详细学习笔记)(上)
Java数据库部分(MySQL+JDBC)(二、JDBC超详细学习笔记)
106 3
Java数据库部分(MySQL+JDBC)(二、JDBC超详细学习笔记)(上)
|
3月前
|
SQL 关系型数据库 MySQL
Java数据库部分(MySQL+JDBC)(一、MySQL超详细学习笔记)(下)
Java数据库部分(MySQL+JDBC)(一、MySQL超详细学习笔记)
37 6
|
3月前
|
存储 关系型数据库 MySQL
Java数据库部分(MySQL+JDBC)(一、MySQL超详细学习笔记)(上)
Java数据库部分(MySQL+JDBC)(一、MySQL超详细学习笔记)
46 4
|
3月前
|
SQL 关系型数据库 MySQL
Java数据库部分(MySQL+JDBC)(一、MySQL超详细学习笔记)(中)
Java数据库部分(MySQL+JDBC)(一、MySQL超详细学习笔记)
30 3
|
3月前
|
开发工具 数据安全/隐私保护 索引
LDAP学习笔记之二:389-DS(RHDS) 增删改查基本操作
LDAP学习笔记之二:389-DS(RHDS) 增删改查基本操作