范式

在关系数据库中,设计数据库时遵从一定的规范要求,可以使得数据库冗余变小。 目前关系数据库有六种范式,不过查了查资料,其实是十种。

  • 1NF 第一范式
  • 2NF 第二范式
  • 3NF 第三范式
  • EKNF 主键范式
  • BCNF Boyce–Codd 范式
  • 4NF 第四范式
  • ETNF 关键元组范式
  • 5NF 第五范式
  • DKNF 域键范式
  • 6NF 第六范式

不过在这里呢,不讲 EKNF 和 ETNF,以八大范式的形式来讲。

123BC45DK6
主键✔️✔️✔️✔️✔️✔️✔️✔️
没有重复组✔️✔️✔️✔️✔️✔️✔️✔️
字段原子性✔️✔️✔️✔️✔️✔️✔️✔️
没有部分函数依赖✔️✔️✔️✔️✔️✔️✔️
没有传递函数依赖✔️✔️✔️✔️✔️✔️
去除主属性对不必要的函数依赖✔️✔️✔️✔️-
每个非平凡的多值依赖都有一个超键✔️✔️✔️-
超键是每个显式连接依赖的一部分✔️✔️-
候选键隐含了每个非平凡的连接依赖关系✔️✔️-
每个约束都是域约束和键约束的结果✔️-
每个连接依赖都是平凡的✔️

✔️: 符合 ❌: 不符合 -: 不适用

1NF

在上表中可以看到,第一范式要求数据库的每个列的值域都是由原子值组成;每个字段的值都只能是单一值,当然还要有主键。

重复组
顾客日期消费
张三1970-01-0180.00
90.00
10.00
李四1970-01-0116.00
王五1970-01-013.00

这种情况下就是不符合第一范式的,消费就是重复组。想要消除重复组的话,只要把每笔记录都转化为单一记录即可:

顾客日期消费
张三1970-01-0180.00
张三1970-01-0190.00
张三1970-01-0110.00
李四1970-01-0116.00
王五1970-01-013.00
主键

上表是没有主键的,如果同一天同一个人消费呢同样的金额,这样的交易做了两次,这个表就有点乱了。

因为这两笔交易是一模一样的,也就是说如果只靠这些数据没有办法分辨这两笔记录。

之所以说它不符合第一范式,是因为上面这样的表示法欠缺一个唯一标识符,而且可以保证在这个数据中唯一标识符不会重复出现。

交易顾客日期消费
1张三1970-01-0180.00
2张三1970-01-0190.00
3张三1970-01-0110.00
4李四1970-01-0116.00
5王五1970-01-013.00
字段原子性

有时候为了方便,可能设计数据库的时候会这样。

姓名联系方式
张三12345678901, 12345@mail.com
张三12345678902

但是这样就违反了字段的原子性,改成这样会更好。

姓名手机号邮箱
张三1234567890112345@mail.com
张三12345678902

再加上主键吧。

编号姓名手机号邮箱
0张三1234567890112345@mail.com
1张三12345678902
2李四1234567890312346@mail.com

2NF

第二范式在第一范式的基础上增加了一点要求,数据表里的所有数据都要和该数据表的键(主键与候选键)有完全依赖关系: 每个非键属性必须独立于任意一个候选键的任意一部分属性。 如果有哪些数据只和一个键的一部分有关的话,就得把它们独立出来变成另一个数据表。

商品 ID(Primary key)价格供应商 ID(Primary key)供应商名称
110.001食品公司
220.001食品公司
333.332饮料公司

这个数据表的每个值都是单一值,所以它符合第一范式。 因为同一个商品有可能由不同的供应商提供,所以得把商品 ID 和供应商 ID 合在一起组成一个主键。

商品和价格之间的关系很正确:同一个商品在不同供应商有可能会有不同的报价,所以价格确实和主键完全相关。

另一方面,供应商的名称只和供应商 ID 有关,这不符合第二范式的原则。

商品 ID价格供应商 ID
110.001
220.001
333.332
供应商 ID供应商名称
1食品公司
2饮料公司

3NF

第三范式要求所有非主键属性都只和候选键有相关性,也就是说非主键属性之间应该是独立无关的。

学号姓名年龄所在学院学院地点学院电话
1张三1语言文化一路向西12345678
2张三1语言文化一路向西12345678
3李四2科学技术一路向南12345679

这个数据表就是符合第二范式但不符合第三范式的,因为其中存在 (学号) → (所在学院) → (学院地点, 学院电话) 的关系。 它存在非关键字段"学院地点"、"学院电话"对关键字段"学号"的传递函数依赖。

学号姓名年龄学院编号
1张三11
2张三11
3李四22
学院编号学院名称学院地点学院电话
1语言文化一路向西12345678
2科学技术一路向南12345679

BCNF

如果对第三范式做进一步加强,那就是 Boyce-Codd 范式了。 BC 范式去除了属性间的不必要的函数依赖。

商店 ID商品 ID数量店长
1188张三
1299张三
237107李四
245511李四
254114李四

对于这张表,存在如下关系:

  • 一个商店对应一个店长
  • 一个商店有多个商品

想让其符合 BCNF,可以改成这样。

商店 ID商品 ID数量
1188
1299
237107
245511
254114
商店 ID店长
1张三
2李四

4NF

前几个方式都是关注属性集合之间的函数依赖,而第四范式关注更一般形式。 第四范式能作用到的范围有限,不是什么场景都能用得到的。 而且比较扯。

学生课程爱好
张三语文篮球
张三语文网球
张三数学网球
李四语文网球
王五语文网球
学生课程
张三语文
张三数学
李四语文
王五语文
学生爱好
张三篮球
张三网球
李四网球
王五网球

5NF

第五范式去除多个关系之间的语义相关。

客户品牌产品
张三ABCS
张三ABCG
张三KCFW
李四KCFW
李四ABCG

如果数据表在 4NF 中并且不包含任何连接依赖关系并且连接应该是无损的,则关系在 5NF 中。当所有表都被分成尽可能多的表以便避免冗余时,满足 5NF。

客户品牌
张三ABC
张三KCF
李四KCF
李四ABC
客户产品
张三S
张三G
张三W
李四W
李四G
品牌产品
ABCS
ABCW
ABCG
KCFW
ABCG

DKNF

DKNF 是去除关系不包含于域约束的其他约束。

如果经验与等级的换算是 等级 * 100,类型有 NPC 和 Player。这张表就是违反 DKNF 的。

玩家类型等级经验值
张三MPC.3322
李四Player.8858
王五Player.4425

可以分离为两张表。

玩家类型经验值
张三MPC322
李四Player858
王五Player425
等级经验
3300
8800
4400

6NF

第六范式,所谓每个连接依赖都是平凡的,通俗来说就是每个表都只能拥有一个主键和不超过一个的属性。 这就意味着,每张表的列数非常的少,除了主键之外,最多只能拥有一列。 看到这个定义之后,是不是有点 No-SQL key-value 数据库的意思。

数据是随着时间不断变化的,也就是我们常说的一句谚语:唯一不变的只有变化本身。 这就要求数据库设计最好是模块化,比较灵活,而且很容易能够跟踪数据的变化。 很可惜,现有的五范式并不能满足这些要求。

这里并不讲第六方式,不是因为别的,因为没这么接触过,不甚了解。

真正的范式

如果你知道自己在做什么,就去做吧,不要让规则束缚了你自己

powered by Gitbook该文件修订时间: 2020-04-10 10:05:54

results matching ""

    No results matching ""

    results matching ""

      No results matching ""