准备知识
超键、候选键、主键
- 超键
超键(super key):在关系中能唯一标识元组的属性集称为关系模式的超键 - 候选键
候选键(candidate key):不含有多余属性的超键称为候选键。也就是关系中的一个属性组,其值能唯一标识一个元组。若从属性组中去掉任何一个属性,它就不具有这一性质了,这样的属性组称作候选键。
主属性:任何一个候选键中的属性称作主属性。(请记住这个概念) - 主键
主键(primary key):用户从一个关系的多个候选键中,选定一个作为主键。
结合具体的例子进行解释,现有学生表如下:
学生(学号,姓名,性别,身份证号)
学号 | 姓名 | 性别 | 身份证号 |
---|---|---|---|
1 | 小王 | 男 | 344 |
2 | 小吴 | 女 | 354 |
3 | 小丽 | 女 | 364 |
4 | 小张 | 男 | 374 |
- 超键
由超键的定义可知,在学生表中含有学号或者身份证号的任意组合都可以唯一标识一个学生,那么它们就是此表的超键。如:(学号)、(身份证号)、(学号,姓名)、(身份证号,性别)等。 - 候选键
候选键属于超键,它是最小的超键,就是说如果再去掉候选键中的任何一个属性它就不再是超键了。对于(学号、姓名)来说,去掉姓名后仍是一个超键,那么它就不是候选键。其中,学生表中的候选键为:(学号)、(身份证号),主属性就是学号、身份证号。 - 主键
主键就是候选键里面的一个,用户可以选择,那么在这里我们选择(学号)作为学生表的主键。 -
函数依赖
这里先给出数学描述,再进行通俗解释。
数学描述
- 通俗理解
函数依赖的英文定义是:The value of one or a group attributes can decide the value of other attributes.
很容易理解,也就是一个或者一组属性的值可以决定其他属性的值。候选键都可以做到。
部分依赖
- 数学描述
- 通俗理解
部分依赖是什么情况呢?
举个例子,现有一关于学生的关系模式Student(学生编号 , 学生姓名, 班级编号, 院系, 课程编号 , 成绩) | 学生编号 | 学生姓名 | 班级编号 | 院系 | 课程编号 | 成绩 | | —- | —- | —- | —- | —- | —- | | S01 | 杨明 | D01 | 思齐 | C01 | 90 | | S02 | 李婉 | D01 | 思齐 | C01 | 87 | | S01 | 杨明 | D01 | 思齐 | C02 | 92 | | S03 | 刘海 | D02 | 述圣 | C01 | 95 | | S04 | 安然 | D02 | 述圣 | C02 | 78 | | S05 | 乐天 | D03 | 省身 | C01 | 82 |
(学生编号#、课程编号#)作为主键,可以唯一标识每条元组,但是对于学生姓名
、学生所属的班级编号
、院系
,这三个属性可以直接通过学生编号
来确定,在这里课程编号#
显得很多余。于是称,学生姓名、班级编号、院系
对(学生编号#、课程编号#)部分函数依赖。
即,非主属性
对键
有部分函数依赖
。
主属性:任何一个候选键中的属性称作主属性。 键在这里理解成候选键
传递依赖
- 数学描述
- 通俗理解
继续以Student表为例, | 学生编号 | 学生姓名 | 班级编号 | 院系 | 课程编号 | 成绩 | | —- | —- | —- | —- | —- | —- | | S01 | 杨明 | D01 | 思齐 | C01 | 90 | | S02 | 李婉 | D01 | 思齐 | C01 | 87 | | S01 | 杨明 | D01 | 思齐 | C02 | 92 | | S03 | 刘海 | D02 | 述圣 | C01 | 95 | | S04 | 安然 | D02 | 述圣 | C02 | 78 | | S05 | 乐天 | D03 | 省身 | C01 | 82 |
学生编号
可以唯一确定他所在的院系
,但是注意到这中间存在传递过程
,即学生编号
唯一确定该学生所对应的班级编号
,班级编号
对应唯一的院系
。我们称,院系
对学生编号
传递函数依赖。
即,非主属性
对键
有部分函数依赖
。
主属性:任何一个候选键中的属性称作主属性。
范式
关系数据库中的模式设计要满足一定的规范,引入了范式这一概念。
不管做哪种范式的设计,最终要的思想是“one fact in one place”,也就是“一事一地”。
1NF
定义:关系中每一分量不可再分。即不能以集合、序列等作为属性。(也就是不能表中套表,要保证数据的原子性。)
举例
学生编号 | 课程编号 |
---|---|
S01 | {C1,C2,C3} |
S02 | {C1,C4} |
它就不满足1NF,因为{C1,C2,C3}和{C1,C4}是集合。
修改为符合1NF:
学生编号 | 课程编号 |
---|---|
S01 | C1 |
S01 | C2 |
S01 | C3 |
S02 | C1 |
S02 | C4 |
2NF
定义:在1NF基础上,消除非主属性对键的部分依赖,则称它符合2NF。
根据上面对部分依赖的分析,对于Student表:
学生编号 | 学生姓名 | 班级编号 | 院系 | 课程编号 | 成绩 |
---|---|---|---|---|---|
S01 | 杨明 | D01 | 思齐 | C01 | 90 |
S02 | 李婉 | D01 | 思齐 | C01 | 87 |
S01 | 杨明 | D01 | 思齐 | C02 | 92 |
S03 | 刘海 | D02 | 述圣 | C01 | 95 |
S04 | 安然 | D02 | 述圣 | C02 | 78 |
S05 | 乐天 | D03 | 省身 | C01 | 82 |
对于学生姓名
、学生所属的班级编号
、院系
,这三个属性可以直接通过学生编号
来确定,在这里课程编号#
显得很多余。也就是,学生姓名、班级编号、院系
对(学生编号#、课程编号#)部分函数依赖。把Student表进行拆分,可以消除部分依赖。
其中,学生表Student如下:
学生编号 | 学生姓名 | 班级编号 | 院系 |
---|---|---|---|
S01 | 杨明 | D01 | 思齐 |
S02 | 李婉 | D01 | 思齐 |
S01 | 杨明 | D01 | 思齐 |
S03 | 刘海 | D02 | 述圣 |
S04 | 安然 | D02 | 述圣 |
S05 | 乐天 | D03 | 省身 |
学生-课程表如下:
学生编号 | 课程编号 | 成绩 |
---|---|---|
S01 | C01 | 90 |
S02 | C01 | 87 |
S01 | C02 | 92 |
S03 | C01 | 95 |
S04 | C02 | 78 |
S05 | C01 | 82 |
3NF
定义:在2NF基础上,消除非主属性对键的传递依赖,则称它符合3NF。
根据上面对传递依赖的分析,对于Student表,学生编号
可以唯一确定他所在的院系
,但是注意到这中间存在传递过程
,即学生编号
唯一确定该学生所对应的班级编号
,班级编号
对应唯一的院系
。我们称,院系
对学生编号
传递函数依赖。
把Student表继续进行拆分,可以消除传递依赖。
其中,学生表Student如下:
学生编号 | 学生姓名 | 班级编号 |
---|---|---|
S01 | 杨明 | D01 |
S02 | 李婉 | D01 |
S01 | 杨明 | D01 |
S03 | 刘海 | D02 |
S04 | 安然 | D02 |
S05 | 乐天 | D03 |
班级-院系表如下:
班级编号 | 院系 |
---|---|
D01 | 思齐 |
D02 | 述圣 |
D03 | 省身 |
BCNF
我当时在看BCNF的时候,这块是最懵的地方,网上找的例子五花八门……解释和过程感觉没有比较详细的,最后反正得到了一个结果orz。我本来想把这个范式按照类似的定义来写的……但是到BNCF发现不能直接写成“在3NF基础上,消除主属性对键的部分依赖、传递依赖,则称它符合BCNF。”
因为这样不太好解释,故而调整了方案。我认为,理解更重要。
先给个文绉绉的定义
换言之,对于关系模式R,如果每一个函数依赖的决定因素都包含键,则R属于BCNF范式。
现在举例,现有关系模式:通讯(城市名,街道名,邮政编码)
函数依赖关系集为:
F={(城市名,街道名)-> 邮政编码,邮政编码 -> 城市名}
也就是一个城市名和一个街道名,对应一个邮政编码;一个邮政编码对应一个城市名。
此时,候选键(城市名,街道名)非主属性邮政编码完全依赖于候选键,且无传递依赖,属于3NF。
那么它是否属于BCNF呢?我们按照下面的定义来看一下,
换言之,对于关系模式R,如果每一个函数依赖的决定因素都包含键,则R属于BCNF范式。
对于决定因素(城市名,街道名),它包含键(城市名,街道名),其实它本身就是键了,没问题;
对于决定因素邮政编码,它不包含键(城市名,街道名)
所以它不属于BCNF。在关系模式R中,如果每一个决定因素都包含码,则R属于BCNF。