范式(Normal Form),它是英国人 E.F.Codd(关系数据库的老祖宗)在上个世纪70年代提出关系数据库模型后总结出来的,范式是关系数据库理论的基础,也是设计数据库结构过程中所要遵循的规则和指导方法。
目前有迹可寻的共有8种范式,依次是:1NF,2NF,3NF,BCNF,4NF,5NF,DKNF,6NF。通常所用到的只是前三个范式,即:第一范式(1NF),第二范式(2NF),第三范式(3NF)。
第一范式
强调原子性,存储的数据应该不可以再分。
考虑这样一个表:
Contract表:
姓名 | 性别 | 电话 |
---|---|---|
第一范式 | 1 | 10001 |
第二范式 | 1 | 10002 |
第三范式 | 1 | 10003 |
如果在实际场景中,一个联系人有家庭电话和公司电话,那么这种表结构设计就没有达到 1NF。要符合 1NF 我们只需把列(电话)拆分:
Contract表(改进后):
姓名 | 性别 | 家庭电话 | 公司电话 |
---|---|---|---|
第一范式 | 1 | 10001 | 20001 |
第二范式 | 1 | 10002 | 20002 |
第三范式 | 1 | 10003 | 20003 |
第二范式
首先是 1NF,强调唯一性,需要实现每一行数据具有唯一可区分的特性,并不能有部分依赖关系。
考虑一个订单明细表(OrderDetail):
OrderID | ProductID | UnitPrice | Discount | Quantity | ProductName |
---|---|---|---|---|---|
101 | 201 | 30 | 7.0 | 1 | 第一范式 |
101 | 202 | 45 | 9.0 | 1 | 第二范式 |
101 | 203 | 60 | 6.0 | 1 | 第三范式 |
因为在一个订单中可以订购多种产品,所以单单一个 OrderID 是不足以成为主键的,主键应该是(OrderID,ProductID)。显而易见 Discount,Quantity完全依赖于主键(OderID,ProductID),而 UnitPrice,ProductName 只依赖于 ProductID。所以 OrderDetail 表不符合 2NF。
不符合 2NF 的设计容易产生冗余数据。
可以把【OrderDetail】表拆分为【OrderDetail】(OrderID,ProductID,Discount,Quantity)和【Product】(ProductID,UnitPrice,ProductName)来消除原订单表中UnitPrice,ProductName多次重复的情况。
OrderDetail表:
OrderID | ProductID | Discount | Quantity |
---|---|---|---|
101 | 201 | 7.0 | 1 |
101 | 202 | 9.0 | 1 |
101 | 203 | 6.0 | 1 |
Product表:
ProductID | UnitPrice | ProductName |
---|---|---|
201 | 30 | 第一范式 |
202 | 45 | 第二范式 |
203 | 60 | 第三范式 |
第三范式
首先是 2NF,强调独立性,消除传递依赖。
考虑一个订单表:
OrderDetail表:
OrderID | ProductID | Discount | Quantity |
---|---|---|---|
101 | 201 | 7.0 | 1 |
101 | 202 | 9.0 | 1 |
101 | 203 | 6.0 | 1 |
Product表:
ProductID | UnitPrice | ProductName |
---|---|---|
201 | 30 | 第一范式 |
202 | 45 | 第二范式 |
203 | 60 | 第三范式 |
第三范式的要求就是一个表只记录一种数据,可以通过拆分【OrderDetail】为【OrderDetail】(OrderID,Discount, Quantity)和【Product】(ProductID,UnitPrice,ProductName)建立两张表,加外间约束Order_Product中间表从而达到 3NF。
OrderDetail表:
OrderID | Discount | Quantity |
---|---|---|
101 | 7.0 | 1 |
101 | 9.0 | 1 |
101 | 6.0 | 1 |
Product表:
ProductID | UnitPrice | ProductName |
---|---|---|
201 | 30 | 第一范式 |
202 | 45 | 第二范式 |
203 | 60 | 第三范式 |
Order_Product表:
OrderID | ProductID |
---|---|
101 | 201 |
101 | 202 |
101 | 203 |