范式
为什么要用范式
我们在学习关系型数据库的时候一定有感觉,关系数据库不就是一个二维表格吗,那么数据库有什么用?
数据库看上去像一个表格,其实不然,比如如下的订单表
,一个订单号X2001对应一个用户,但是还对应了两行产品,非常不规范。
要想把这个表规范化,可以使用范式
。引入范式的主要目的在于:解决冗余的问题
第一范式
那么如何规范化
呢?可以拆分成两个表格。
一个是订单表
一个订单号可以唯一的确定一行
一个是细节表
,一个订单号+产品编码才可以唯一的确定一行。
拆分以后就可以保证一个单元格只有一个值了
所以我们说订单表
的主键是 (订单号), 细节表
的主键是(订单号,产品编码), 这是一个复合主键
第二范式
再看看订单细节表
, 产品名称
和单价
实际上并不依赖于 订单号
。
如果想添加一个新的产品, 你会发现没法放入这张表, 因为没有订单号!
所以还需要再次拆分。
拆分以后,表4.1订单细节表
的主键还是(订单号,产品编码),但是剩下的属性(数量)肯定是完全依赖于主键的。
表4.2产品表也类似,主键是产品编码
,剩下的属性都依赖于产品编码
所有属性都依赖于
主键
的情况就是第二范式
第三范式
我们再回过头来看一下表格3 订单表
,它的主键是订单号
,所有的属性都依赖于主键,已经是第二范式。 但是我们发现,订单号能决定用户ID,用户ID能决定用户名称,这就出现了依赖传递
:订单号->用户ID->用户名称
那么可以再拆分
没有传递依赖了, 我们可以称之为 第三范式
为了满足范式要求,需要把一张大表拆分开,到时候查询岂不是非常麻烦?是的,需要将这些表Join
起来,如果数据量大的时候,连接非常耗时。有时我们需要违反范式,做点数据冗余。
总结
总结一下:
第一范式:字段是不可再分的,也就是不存在一个字段中存在两个及以上值的情况。
第二范式:所有属性都依赖于主键,其他不相关的都拆分出去了。
第三范式:不存在某个列不依赖于
非主键
的列,没有依赖传递了
参考
主要改编自张大胖学数据库