基本定义
候选键:若关系中的某一属性或属性组的值能唯一的标识一个元组,而其任何真子集都不能再标识,则称该属性或属性组为候选键(候选码)。
超码:一个属性集合始终能够确保在关系中能唯一标识元组,则成为超码;它是候选键的超集,我们也可以把候选键定义为“最小超码”,也就是不含有多余属性的超码。
主键:数据库管理系统通常都需要将每个关系中的某个候选键定义为主键,亦即这个候选键是区分不同元组时首选的识别方式,例如外键通常就是引用主键而非其他候选键。
外键:某个数据库表的主键会放在另一个数据表,当做属性以创建彼此的关系,而这个属性就是外键。
主属性:在一个关系中,如果一个属性是构成某一个候选键的属性集中的一个属性,则称它为主属性。
非主属性:不包含在任何一个候选键中的属性称为非主属性。
完全函数依赖和部分函数依赖:如果非主属性B函数依赖于构成某个候选键的一组主属性A,而且A的任何一个真子集不能被B函数依赖,则称B完全函数依赖于A;反之,若B能函数依赖于A的真子集,则称B部分函数依赖于A。
1NF
满足1NF的条件:数据库表中的每个属性(字段)都不可再分,即不存在如下形式:
属性1 | 属性2 | 属性3 | |
属性2.1 | 属性2.2 |
2NF
在1NF的前提下,满足2NF的条件:关系中每一个非主属性(注意是非主属性)完全依赖于候选键;如果某个主属性部分依赖于候选键,而非主属性都完全依赖于候选键,则仍然认为该关系满足2NF的条件,可以参考下文中BCNF的例子。2NF消除了部分依赖。
3NF
在2NF的前提下,满足3NF的条件:所有的非主属性都必须和每个候选键有直接相关,也就是说所有非主属性互相之间应该是无关的。3NF消除了传递依赖。
对于下面这种关系, {A , B} -> C C->B 它并不满足3NF,实际上,它连2NF也不满足,因为它一定还包含另一个候选键{A , C},而B会部分依赖于{A , C},因此它不满足2NF。
下面提供一个3NF的例子:
订单编号 (Order Number) (主键) |
客户名称 (Customer Name) | 单价 (Unit Price) | 数量 (Quantity) | 小计 (Total) |
---|---|---|---|---|
1000 | David | $35.00 | 3 | $105.00 |
1001 | Jim | $25.00 | 2 | $50.00 |
1002 | Bob | $25.00 | 3 | $75.00 |
在本例中,非主键字段完全依赖于主键订单编号,也就是说唯一的订单编号能导出唯一非主键字段值,符合第二范式。第三范式要求非主键字段之间不能有依赖关系,显然本例中小计依赖于非主键字段单价和数量,不符合第三范式。小计不应该放在这个数据表里面,只要把单价乘上数量就可以得到小计了;如果想要符合第三范式的话,就把小计拿掉吧。
BCNF
在1NF的前提下,满足BCNF条件:
- 所有非主属性对每一个候选键都是完全函数依赖;
- 所有的主属性对每一个不包含它的候选键,也是完全函数依赖;
- 没有任何属性完全函数依赖于非候选键的任何一组属性。
通过上述条件可以看出,BCNF是在3NF的基础上加上更严格约束(主要体现在第二条),每个BCNF关系是3NF的子集,有从属关系。
BCNF区别于3NF的关键就是上述第二条,举例如下:
假设仓库管理关系表为StorehouseManage(仓库ID, 存储物品ID, 管理员ID, 数量),且有一个管理员只在一个仓库工作;一个仓库可以存储多种物品。这个数据库表中存在如下决定关系: (仓库ID, 存储物品ID) →(管理员ID, 数量) (管理员ID, 存储物品ID) → (仓库ID, 数量) 所以,(仓库ID, 存储物品ID)和(管理员ID, 存储物品ID)都是StorehouseManage的候选键,表中的唯一非主属性为数量,这个关系是符合第三范式的。但是,由于存在如下关系: (仓库ID) → (管理员ID) (管理员ID) → (仓库ID) 即存在主属性对其他候选键的部分函数依赖,所以不符合BCNF。