关系数据库范式
在关系数据库中,关系表通常记作R,字段在定义中被称作属性或字段列。
关系数据库中的关系是要满足一定要求的,满足不同程度要求的为不同范式。满足最低要求的属于第一范式,简称1NF。在第一范式中满足进一步要求的属于第二范式,其余依次类推。
从范式来讲,主要是E.F. Codd做的工作,1971~1972年他系统地提出了1NF、2NF、3NF的概念,讨论了规范化的问题。1974年,Codd和Boyce又共同提出了一新范式,即BCNF。1976年Fagin又提出了4NF。后来又有人提出了5NF。
所谓“第几范式”,是表示关系的某一种级别。所以经常称为某一关系模式R为第几范式。现在把范式这个概念理解成符合某一种级别的关系模式的集合,则R为第几范式就可以写成 $R\in xNF$ 。
对于各种范式之间的联系有:
\[5NF \subset 4NF\subset BCNF\subset 3NF\subset 2NF\subset 1NF\]
一个第一级别范式的关系模式,通过模式分解(Schema Decomposition)可以转换为若干个高一级别范式的关系模式的集合,这种过程就叫规范化(Normalization)。
基本术语
定义1 函数依赖:设R是属性集U上的关系模式。X,Y是U的子集。若对于R的任意一个可能的关系r,r中不可能存在两个元组在X上的属性值相等,而在Y上的属性值不等,则称X函数确定Y,或Y函数依赖于X,记为X→Y。
定义2 非平凡的函数依赖:若X→Y,但是 $Y\not\subseteq X$ ,则称X→Y是非平凡的函数依赖。
定义3 平凡的函数依赖:若X→Y,但是 $Y\subseteq X$ ,则称X→Y是平凡的函数依赖。
定义4 完全函数依赖:在R中,若X→Y,并且对于X的任何一个真子集X',都有X' $\nrightarrow$ Y,则称Y对X完全函数依赖。
定义5 部分函数依赖:若X→Y,但是Y不完全函数依赖于X,则称Y对X部分函数依赖(Partial Functional Dependency)。
第一范式(1NF)
定义:如果关系R中所有属性的值域都是不可再分解,那么关系模式 $R\in1NF$ 。
那么,符合第一范式的特点有:
- 有主关键字
- 主键不能为空
- 主键不能重复
- 各字段值不可以再分
例如:
Sno | Name | Gender | Contact |
---|---|---|---|
20040901 | John | Male | Email: John@gmail.com, Phone:67983021 |
20040901 | Mary | Female | Email: Mary@gmail.com, Phone:87302805 |
上面的关系表就不符合第一范式,因为:
- 主键值重复;
- Contact字段可以再分解为Email和Phone两个字段。
所以,正确的模式应该为(注:下划线是主键标志,下同):
Sno | Name | Gender | Phone | |
---|---|---|---|---|
20040901 | John | Male | John@gmail.com | 67983021 |
20040901 | Mary | Female | Mary@gmail.com | 87302805 |
第二范式(2NF)
定义:如果关系模式R是第一范式的,而且关系中每一个非主属性完全函数依赖于主键,称 $R\in2NF$ 。
所以,若想将关系模式由第一范式转化为第二范式,其主要任务就是:在满足第一范式的前提下,消除部分函数依赖。
Sno | Name | Gender | Phone | ClassNo | ClassAddress | |
---|---|---|---|---|---|---|
01 | John | Male | John@gmail.com | 67983021 | 200401 | A楼2号 |
01 | Mary | Female | Mary@gmail.com | 87302805 | 200402 | A楼3号 |
这个表完全满足于第一范式。其中,主键由Sno和ClassNo组成,这样才能定位到指定行。
但是,ClassAddress部分依赖于关键字(ClassNo→ClassAddress),而其他非主属性完全函数依赖与关键字。
所以要将上述关系表分解为两个表,即可以满足第二范式,如下:
关系一:
Sno | Name | Gender | Phone | ClassNo | |
---|---|---|---|---|---|
01 | John | Male | John@gmail.com | 67983021 | 200401 |
01 | Mary | Female | Mary@gmail.com | 87302805 | 200402 |
关系二:
ClassNo | ClassAddress |
---|---|
200401 | A楼2号 |
200402 | A楼3号 |
第三范式(3NF)
定义:关系模式R中若不存在这样的码X,属性组Y及非主属性Z( $Z\not\subseteq Y$ )使得X→Y,Y→Z成立, $Y\nrightarrow X$ ,则称 $R\in3NF$ 。
所以,在满足第二范式的前提下,消除传递依赖即可实现第三范式。
例:
Sno | Name | Gender | BounsLevel | Bouns | |
---|---|---|---|---|---|
20040901 | John | Male | John@gmail.com | 优秀 | ¥1000 |
20040902 | Mary | Female | Mary@gmail.com | 良好 | ¥600 |
这个关系完全满足了第二范式。但是,BounsLevel和Bouns存在传递依赖关系,所以应更改为:
关系一:
Sno | Name | Gender | BounsNo | |
---|---|---|---|---|
20040901 | John | Male | John@gmail.com | 1 |
20040902 | Mary | Female | Mary@gmail.com | 2 |
关系二:
BounsNo | BounsLevel | Bouns |
---|---|---|
1 | 优秀 | ¥1000 |
2 | 良好 | ¥600 |
这里,使用用BounsNo作为主键。
基于两个原因
- 不要用字符作为主键。
- 如果等级名称更改了,不叫 1,2 ,3或优、良,这样就可以方便更改,所以一般优先使用与业务无关的字段作为关键字。
一般满足前三个范式就可以避免数据冗余。
第四范式(4NF)
主要任务:满足第三范式的前提下,消除多值依赖
Product | Agent | Factory |
---|---|---|
Car | A1 | F1 |
Bus | A1 | F2 |
Car | A2 | F2 |
注意:在这里,Car的定位,必须由Agent和Factory才能得到(所以主键由Agent和Factory组成),Product依赖了agent和factory两个属性
所以正确的关系模式为:
关系表一:
Product | Agent |
---|---|
Car | A1 |
Bus | A1 |
Car | A2 |
关系表二:
Product | Factory |
---|---|
Car | F1 |
Bus | F2 |
Car | F2 |
第五范式(5NF)
定义: 如果关系模式R中的每一个连接依赖,都是由R的候选键所蕴含,则称 $R\in5NF$ 。
看到定义,就知道是要消除连接依赖,并且必须保证数据完整
例子
A | B | C |
---|---|---|
A1 | B1 | C1 |
A2 | B1 | C2 |
A1 | B2 | C1 |
A2 | B2 | C2 |
如果要定位到特定行,必须三个属性都为关键字。
所以关系要变为三个关系,分别是A和B,B和C,C和A
如下:
关系表一:
A | B |
---|---|
A1 | B1 |
A1 | B2 |
关系表二:
B | C |
---|---|
B1 | C1 |
B1 | C2 |
关系表三:
C | A |
---|---|
C1 | A1 |
C1 | A2 |
范式可以避免数据冗余,减少数据库的空间,减轻维护数据完整性的麻烦,但是操作难,因为需要联系多个表才能得到所需要数据,而且越高范式性能就会越差。要权衡是否使用更高范式是比较麻烦。
一般,在做项目时用得最多的也就是第三范式,性能好而且方便管理数据。