之所以使用范式,往往是设计不规范的数据库表可能造成大量的数据冗余,也可能在发生插入、删除、修改操作后出现各种各样的不合理的问题。
1)1NF(第一范式):属性不可分, 数据库表的每一列都是不可分割的基本数据项。 如“电话号码”这个属性可以继续被分割为“办公电话”、“手机号码”等属性,在第一范式的语义下不应该被作为单独的一列出现。
设有关系 R(S,D,M), 其函数依赖集 F={S,D,D->M}. 则关系 R 至多满足 第一范式。 {S,D}为候选键,M部分依赖于候选键,所以不属于第二范式,是第一范式。
根据关系数据库规范化理论,关系数据库中的关系要满足第一范式。下面“部门”关系中,因哪个属性而使它不满足第一范式?( 部门成员)。
部门(部门号,部门名,部门成员,部门总经理)
-
部门总经理
-
部门成员
-
部门名
-
部门号
2)2NF(第二范式):符合1NF,并且非主属性完全依赖于R的某个候选键。(2NF是对记录的惟一性约束,要求记录有惟一标识,即实体的惟一性,更通俗说有主键ID)
必须先满足第一范式。 数据库表中的每一行必须可以被唯一的区分,即每一行中有一个唯一标识将这行与其他行区分出来,这个唯一标识就是我们常说的主键。在2NF的语义下,所有非主键的字段都要依赖主键。比如在学生表中我们用学生id作为主键,那么当我们需要查询一个学生的时候,通过他的id号应该可以唯一地定位到这个学生,会并且只会查出一行。
3)3NF(第三范式):符合2NF,并且,消除传递依赖,每个非主属性都不依赖于R中的候选键。(3NF是对字段冗余性的约束,即任何字段不能由其他字段派生出来,它要求字段没有冗余)一般选择第三范式比较好。
关系模式R中的属性全是主属性,则R的最高范式必定是( C)。
-
1NF
-
2NF
-
3NF
-
BCNF
必须先满足第二范式。非主键字段都与主键字段有直接依赖关系,不存在传递依赖(所谓传递函数依赖,指的是如果存在"A → B → C"的决定关系,则C传递函数依赖于A。)。可以理解为非主键字段只依赖主键字段,而不依赖其它的非主键字段。
比如员工表的字段构成为:员工id(主键),姓名,性别,年龄,所属部门,部门经理姓名,部门电话。
这里所有的非主键字段并不是直接依赖于主键“员工id”, 可以看到“部门经理姓名”和“部门电话”这两个属性依赖于“所属部门”,而“所属部门”又依赖于主键“员工id”,这就是传递依赖,这里可将该员工表的表结构改成:员工id(主键),姓名,性别,年龄,部门名称
单独提出部门表结构为:部门名称(主键),部门经理id ,部门电话
4)BCNF :第三范式的扩展和加强。
这里用网上看到的一个例子:
表结构: 仓库id 管理员id 物品id 物品数量
其中管理员和仓库的关系是一对一,仓库和物品的关系是一对多;
这个设计符合第一、二、三范式,即每列不可分割、主键唯一且不存在传递依赖;
可看到依赖关系有 管理员id 依赖 仓库id, 物品id 依赖 仓库id。 即存在主键到主键再到非主键的传递依赖关系。
这里的主要问题是,仓库id和管理员id这两个关键字段之间的关系被耦合到每一个实例中了,这导致:
a) 表中没有数据的时候,无法描述仓库和管理员之间的关系
b) 一个仓库的管理员替换后,表中所有含有该仓库的实例中的管理员id都要被修改
解决办法是将二者的关系提出来单独建表。
则原表结构改为:仓库id 物品id 物品数量
增加表的结构: 仓库id 管理员id
这样 仓库和管理员的关系 及 仓库和物品的关系 就解耦合了。
链接:https://www.nowcoder.com/questionTerminal/6a3526e9523747d991ea6bdf9d7fb9fe
来源:牛客网
在某企业中,有关系W(工号,姓名,工种,工资),其中工资由工种唯一决定。将其规范化到第三范式,正确的答案是?D
-
A W1(工号,姓名) W2(工种,工资)
-
B W1(工号,工种,工资) W2(工号,姓名)
-
C W1(工号,姓名,工种) W2(工种,工资)
-
D 以上都不对
5)4NF(第四范式):必须先满足第三范式,要求把同一表内的多对多关系删除。简单来说就是将表中的多值属性拆分出来,分别建表。
比如在用户表中有一个非主键字段“电话号码”,某一行实例的“电话号码”内容可能是手机号码,可能是座机号码,也可能是多个内容的直接组合(如“电影”属性中填“动作,喜剧,科幻”), 这就是多值属性。
例:
用户表包含一个多值字段“爱好”,某个实例内容可能为:
用户id 姓名 爱好
1 John 足球、游泳、植物大战僵尸
这种情况可以再单独拆出一个爱好表,如下:
字段: 用户id 爱好
实例: 1 足球
实例: 1 游泳
实例: 1 植物大战僵尸
实例: 2 乒乓球
实例: 3 野外求生
在网上看到一种方案是直接加一个字段来约束多值属性内容,如下:
字段: 用户id 电话类别 电话号码
实例: 1 手机 12345678
实例: 2 家庭座机 020-123456
实例: 3 手机 22345678
这种设计不符合第三范式,电话类别这个属性和主键是没有依赖关系的,它仅仅用来约束电话号码的内容。 优点是较上述解决办法可以减少多表查询的开销。
范式是人们在具体的业务场景中遇到问题逐渐总结出来的通用解决思路,在实际开发中如果并不常用到某些范式,可能只是问题和数据的规模还没达到。