2、第二范式2NF
定义:数据库表中不存在非关键字段对任一候选关键字段的部分函数依赖,即符合第二范式。
简单的说就是不要字段冗余
《注:什么是函数依赖,详见百度百科(http://baike.baidu.com/view/40008.htm)。
如果一个表中某一个字段A的值是由另外一个字段或一组字段B的值来确定的,就称为A函数依赖于B。》
2NF可以减少插入异常,删除异常和修改异常。
简单的说,一方面,第二范式肯定要满足第一范式,否则就没有必要谈第二范式。
另一方面,当某张表中的非主键信息不是由整个主键函数来决定时,即存在依赖于该表中不是主键的部分或者依赖于主键一部分的部分时,通常会违反2NF。
我们再来看上面的满足1NF的表1-2
CardNo | StudentNo | StudentName | Sex | Academy | Major | class | CardCash | UserID | UserLevel | Date | Time |
001 | 021101 | 小明 | 男 | 教育学院 | 心理系 | 1 | 100 | Operator | 操作员 | 2011/10/03 | 09:00 |
我们看到,在这张表中,通过CardNo和StudentNo就可以确定StudentName,Sex,Academy,Major,class,CardCash,UserID,Date,Time。所以可以把CardNo和StudentNo的组合作为主键。
但是,我们发现CardCash并不完全依赖于CardNo和StudentNo,仅仅通过CardNo就可以确定CardCash,因为一张卡,一定会有卡内金额。这就造成了部分依赖。出现这种情况,就不满足第二范式。
修改为:
我们再来看另一个例子,学生上下机记录表,会更明显些。表2-1
CardNo | StudentNo | StudentName | Sex | Department | Major | class | OnDate | OnTime | OffDate | OffTime | ConsumeTime | ConsumeMoney |
001 | 0211 | 小明 | 男 | 教育学院 | 心理系 | 1 | 2011/10/14 | 09:00 | 2011/10/14 | 10:00 | 1 | 2 |
我们看到,在这张表中,StudentName,Sex,Department,Major,class都是直接依赖于StudentNo,而不依赖与表中的其他字段,这样的设计也不符合2NF非主键信息不是由整个主键函数来决定时。
我们可以把1-2和2-1优化为:
3-1
StudentNo | CardNo | UserID | UserLevel | Date | Time |
021101 | 001 | Operator | 操作员 | 2011/10/03 | 09:00 |
3-2
CardNo | CardCash |
001 | 98 |
3-3
CardNo | OnDate | OnTime | OffDate | OffTime | ConsumeTime | ConsumeMoney |
001 | 2011/10/14 | 09:00 | 2011/10/14 | 10:00 | 1 | 2 |
3-4
StudentNo | StudentName | Sex | Academy | Major | class |
021101 | 小明 | 男 | 教育学院 | 心理系 | 1 |
----------------------------------------
第二范式
每一行的数据只能与其中一列相关,即一行数据只做一件事。只要数据列中出现数据重复,就要把表拆分开来。
一个人同时订几个房间,就会出来一个订单号多条数据,这样子联系人都是重复的,就会造成数据冗余。我们应该把他拆开来。
这样便实现啦一条数据做一件事,不掺杂复杂的关系逻辑。同时对表数据的更新维护也更易操作。
----------------------------------------
2.第二范式(确保表中的每列都和主键相关)
第二范式在第一范式的基础之上更进一层。第二范式需要确保数据库表中的每一列都和主键相关,而不能只与主键的某一部分相关(主要针对联合主键而言)。也就是说在一个数据库表中,一个表中只能保存一种数据,不可以把多种数据保存在同一张数据库表中。
比如要设计一个订单信息表,因为订单中可能会有多种商品,所以要将订单编号和商品编号作为数据库表的联合主键,如下表所示。
订单信息表
这样就产生一个问题:这个表中是以订单编号和商品编号作为联合主键。这样在该表中商品名称、单位、商品价格等信息不与该表的主键相关,而仅仅是与商品编号相关。所以在这里违反了第二范式的设计原则。
而如果把这个订单信息表进行拆分,把商品信息分离到另一个表中,把订单项目表也分离到另一个表中,就非常完美了。如下所示。
这样设计,在很大程度上减小了数据库的冗余。如果要获取订单的商品信息,使用商品编号到商品信息表中查询即可。