当设计关系型数据库时,需要遵从不同的规范要求,设计出合理的关系型数据库。这些不同的规范要求被称为不同的范式(Normal Form 简称NF)。越高的范式数据库的冗余越小。应用数据库范式可以带来很多好处。但是最主要的目的是为了消除重复的数据,减少数据的冗余,让数据库内的数据更好的组织,让磁盘空间得到更有效的利用。范式的缺点:范式是的查询变得更为复杂,在查询时需要更多的连接,一些复合索引的列由于范式化的需要被分割到不同的表,导致索引策略不佳。现在数据库设计最多满足3NF,普遍认为范式过高,虽然具有对数据关系更好的约束性,但也导致数据关系表增加而令数据库IO更易繁忙,原来交由数据库处理的关系约束现更多在数据库使用程序中完成。
以下先介绍关系型数据库中的几个关系键:
主键(PRIMARY KEY / UNIQUE KEY):数据库表中对储存数据对象予以唯一和完整标识的数据列或属性的组合。一个数据表只能有一个主键,且主键的取值不能缺失,即不能为空值(Null)。
超键(SUPERKEY 超码):是在数据库关系模式设计中能够唯一标示多元组(即“行”)的属性集。包含所有属性的集叫做明显(平凡)超键。
候选键(CANDIDATE KEY 候选码):
是某个关系变量的一组属性所组成的集合,它需要同时满足下列两个条件:
满足第一个条件的属性集合称为超键,因此我们也可以把候选键定义为“最小超键”,也就是不含有多余属性的超键。
候选键的重要性是它们能够在关系中唯一标识出不同的元组,因此超键也是在设计数据库模式时需要指定的最重要的约束之一。由于在关系模型中,每个关系都是一个集合(没有重复的元素),所以每个关系都至少有一个候选键(因为所有属性组合必然是个超键)。但是在某些关系型数据库中表也能代表多重集,所以在每个关系中都显式地定义至少一个候选键是一条很重要的设计原则。数据库管理系统通常都需要将每个关系中的某个候选键定义为主键,亦即这个候选键是区分不同元组时首选的识别方式,例如外键通常就是引用主键而非其他候选键。
外键(FOREIGN KEY):其实在关系数据库中,每个数据表都是由关系来连系彼此的关系,父数据表(Parent Entity)的主键(primary key)会放在另一个数据表,当做属性以创建彼此的关系,而这个属性就是外键。
代理键(SURROGATE KEY):在关系型数据库设计中,代理键(英语:surrogate key)是在当数据表中的候选键都不适合当主键时,例如数据太长,或是意义层面太多,就会请一个无意义的但唯一的字段来代为作主键。
在实践中,代理键值通常是个自动递增的数字。在Sybase或SQL Server,用identity column标识代理键,PostgreSQL用serial,Oracle用SEQUENCE,在MySQL用标记有AUTO_INCREMENT的字段。
自然键(NATURAL KEY):自然键(英语:natural key)与代理键相反,它是在自然生活中唯一确定一个事物的标识。身份证号(理论上,假设没有因技术原因造成的重复)就是一个自然键,用于确定一个人。
-------------------------------------------------------------------------------------------------------------------------------------------------------------
第一范式(1NF):是为了要排除 重复群 的出现,所采用的方法是要求数据库的每个列的值域都是由原子值组成;每个字段的值都只能是单一值。
大多数的 RDBMS (关系数据库) 允许用户在定义数据表的时候不去指定主键,不过这么一来这种数据表就不匹配第一正规化了。从某个角度看来,不允许重复群的出现是关系数据库表示信息的方法,RDBMS 里数据表每一笔记录的每一个字段都只能有一个值。举例来说,如果定义了一个叫做 Favorite Number 的整数字段,每一笔记录的 Favorite Number 这个字段都只会是一个整数 (或是无);这也就是说,如果设置了主键的话,理论上不可能会有任何关系数据库的数据表会违反第一正规化的原则。不过就算是在这种情况下,还是可以设计出在骨子里违反第一正规化的数据表。最简单的方法就是把多个有意义的值编码过后存进一个字段里,然后在数据表中用很多字段来表达同一个事实。
第二范式(2NF):要求数据表里的所有数据都要和该数据表的键(主键与候选键)有完全依赖关系:每个非键属性必须独立于任意一个候选键的任意一部分属性。如果有哪些数据只和一个键的一部分有关的话,就得把它们独立出来变成另一个数据表。如果一个数据表的键只有单个字段的话,它就一定匹配第二范式。
一个数据表匹配第二范式当且仅当
第三范式(3NF):要求所有非键属性都只和候选键有相关性,也就是说非键属性之间应该是独立无关的。
BC范式(BCNF):BCNF与第三范式的不同之处在于:第三范式中不允许非主属性被另一个非主属性决定,但第三范式允许主属性被非主属性决定;而在BCNF中,任何属性(包括非主属性和主属性)都不能被非主属性所决定。
任何一个BCNF必然满足:
函数依赖:
通俗描述:
描述一个学生的关系,可以有学号(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传递函数依赖。
在R(U)中,如果X->Y, Y->Z, 则称Z对X传递函数依赖。
第四范式(4NF):第二范式、第三范式、BC范式关注于属性集合之间的函数依赖;而第四范式关注更一般形式称作多值依赖。
多值依赖:关系数据库的一个表中的列头分为不相交的三组:X, Y, Z。在一行的特定上下文中,称上述列组的数据值为x, y, z。多值依赖X {\displaystyle \twoheadrightarrow } Y,意味着如果选择表中的任何值x(记作xc),从而确定该表中所有的xcyz列表,如果xc关联着同一个y的值,不论z的任何取值。实质上,z的存在不提供任何信息能约束到y的可能值。也可以表述为,定义域的每一个值,都能确定值域中的一个值的集合。
平凡多值依赖 X {\displaystyle \twoheadrightarrow } Y是或者Y是X的子集,或者X与Y一起形成了该关系的整个属性集合。
函数依赖是多值依赖的特例。函数依赖X → Y,那么每个x确定了确切一个y值,而不能是多个。
第五范式(5NF):也称投影-连接范式(project-join normal form,PJ/NF)是数据库规范化的一个级别,以去除多个关系之间的语义相关。一张表满足第五范式当且仅当它的每个连接依赖可由候选键推出。
R连接依赖于 *{A, B, … Z},定义为A, B, … Z都是R的属性的子集,且A, B, … Z的连接(join)等于R。R上的连接依赖 *{A, B, … Z}可由R的候选键推出,当且仅当A, B, …, Z的每一个都包含了R的超键。
表T满足第五范式意味着它不能被无损分解为几个更小的表。分解后的每个小表与表T拥有相同的候选键的情形被排除不予考虑(作为平凡情形)。
DK范式(DKNF): 是数据库规范化的一个级别,以去除关系不包含于域约束(domain constraint)的其他约束。
域约束指出给定属性的取值范围。键约束指出这几个属性唯一确定了表中的一行。
域键范式使得一个关系的所有约束都是键与域(domain)定义的逻辑蕴涵;因而执行对键与域上的限制与条件后,将导致所有的约束都满足。满足域键范式,使得数据库避免了不是清晰的域约束或键约束的一般性约束。这种一般性约束往往需要特殊编程(如存储过程)来检验是否满足。
第三范式, BC范式, 第四范式与第五范式是域键范式的特例。因为函数依赖、多值依赖与连接(join)依赖都可以转换为(超)键。这些范式对域约束没有讨论,可看作没有域约束。
第六范式(6NF):根据Christopher J. Date的基于关系代数的定义,关系算符(relational operator),如连接(join)可以推广到自然处理间隔数据(interval data),如日期序列或时间间隔, 例如时间数据库。第六范式基于这种推广的join:
数据库的一个关系R满足第六范式,当且仅当R没有非平凡连接依赖。平凡的连接依赖是指R的至少一个投影(projections)包含R的一个候选键。显然,第五范式是第六范式的特例。
第六范式适合使用了间隔数据的时态数据库。