目录

第一范式(原子性)

第二范式(主键唯一性)

第三范式(原子性+主键唯一性)

BC范式(3NFplus)


第一范式(原子性

确保每列保证原子性,保证这个属性(字段)不能在被分割。

不符合第一范式:

订单
————————————————————–
| 订单编号 | 产品名称| 产品价格 |
————————————————————–
| 1 | 手机, 电脑, 鼠标 | 3000, 6000, 100|
| 2 | 相机, 耳机| 2000, 300 |
————————————————————–

在这个例子中,”产品名称”和”产品价格”字段都包含了多个值,使用逗号分隔。这样的设计违反了第一范式(1NF),因为一个字段应该只包含一个值。

为了符合第一范式(1NF),我们可以将每个产品拆分成单独的行,如下所示:

订单
———————————–
| 订单编号 | 产品名称 | 产品价格 |
———————————–
| 1 | 手机| 3000|
| 1 | 电脑| 6000|
| 1 | 鼠标| 100 |
| 2 | 相机| 2000|
| 2 | 耳机| 300 |
———————————–
在上述例子中,每个产品都被拆分成了单独的行,每行分别包含一个产品名称和对应的产品价格。这样就符合了第一范式(1NF),每个字段都是原子性的,不可再分。

第二范式(主键唯一性

第二范式在第一范式的基础上,消除了非主属性对于码的部分函数依赖。且增加了一列,这一列为主键列,非主属性都依赖主键列。且没有包含在主键中的列必须完全依赖于主键,而不能只依赖于主键的一部分,也就是说在一个数据库表中,一个表中只能保存一种数据,不可以把多种数据保存在同一张数据库表中。

例子:一个不符合第二范式可以是一个包含重复数据的数据库表。举个简单的例子,假设我们有一个存储订单信息的数据库表,其中包含订单号、顾客姓名和顾客地址等字段:

OrderDetails
———————————–
| OrderID| CustomerName | CustomerAddress |
———————————–
| 1 | Alice| 123 Main St |
| 2 | Bob | 456 Park Ave |
| 3 | Alice| 123 Main St |
———————————–

在这个例子中,可以看到同一个顾客的姓名和地址信息出现了多次。这种情况下,就不符合第二范式(2NF),因为有部分字段依赖于订单号,而另一部分字段依赖于顾客姓名。这样的表结构存在以下问题:

  1. 数据冗余:同一个顾客的姓名和地址信息重复出现,会导致数据冗余,增加了存储空间的消耗。

  2. 更新异常:如果需要更新顾客的地址,那么就需要同时更新多条记录,容易出现更新异常,导致数据不一致。

第三范式(原子性+主键唯一性

第三范式在第二范式的基础之上,消除了非主属性对于码的传递函数依赖。就是说任何非主属性不依赖于其它非主属性。

一个不符合第三范式(3NF)的例子可以是一个存储产品信息的数据库表,其中包含了产品编号、产品名称、供应商编号、供应商名称和供应商地址等字段:

Products
————————————————-
| ProductID| ProductName | SupplierID | SupplierName | SupplierAddress |
————————————————-
| 1| Laptop| 101| ABC Inc | 123 Main St |
| 2| Smartphone| 102| XYZ Ltd | 456 Park Ave|
| 3| Tablet| 101| ABC Inc | 123 Main St |
————————————————-

在这个例子中,可以看到存在以下问题:

  1. 数据冗余:同一个供应商的名称和地址信息重复出现,会导致数据冗余,增加了存储空间的消耗。

  2. 更新异常:如果需要更新某个供应商的地址,那么就需要同时更新多条记录,容易出现更新异常,导致数据不一致。

为了符合第三范式,我们可以将上述表拆分成两个表:

Products
———————————
| ProductID| ProductName |
———————————
| 1| Laptop|
| 2| Smartphone|
| 3| Tablet|
———————————

Suppliers
———————————
| SupplierID | SupplierName | SupplierAddress |
———————————
| 101| ABC Inc | 123 Main St |
| 102| XYZ Ltd | 456 Park Ave|
———————————
这样就将产品信息和供应商信息分离开来,避免了数据冗余和更新异常,使得数据库表符合第三范式

BC范式(3NFplus)

BC范式(Boyce-Codd Normal Form)是关系数据库设计中的一种标准化范式。它建立在第三范式(3NF)的基础上,通过进一步消除非主属性对候选键的部分依赖来减少数据冗余。

简单来说,BC范式要求:

  1. 每个非主属性都完全依赖于候选键。也就是说,如果一个属性只依赖于候选键的一部分而不是全部,那么它就不符合BC范式。

  2. 所有的函数依赖都应该是候选键的超键。也就是说,任何非候选键的属性都不应该决定其他非候选键的属性。

BC范式的目标是消除数据冗余,并且确保数据的一致性和完整性。通过将关系数据库设计满足BC范式,可以提高数据库的性能和可维护性。

需要注意的是,BC范式是对关系数据库设计的理论指导,并不是必须遵守的绝对规则。在某些情况下,根据实际需求和性能考虑,可能需要在范式化和反范式化之间做出权衡。

举个例子:假设我们有一个关系数据库用于存储员工信息,包含以下字段:员工编号、姓名、部门、工资。

  1. 员工编号是主键(候选键),每个员工的编号唯一标识其身份。

  2. 姓名、部门和工资都完全依赖于员工编号。

在第三范式(3NF)下,我们可以将数据设计如下:

员工表------------------------------------------------| 员工编号 | 姓名 | 部门 | 工资 |------------------------------------------------| 001| 张三| 技术部| 5000|| 002| 李四| 销售部| 6000|| 003| 王五| 财务部| 7000|------------------------------------------------

这个设计符合第三范式(3NF),因为每个非主属性(姓名、部门、工资)都完全依赖于候选键(员工编号),没有冗余数据

然而,如果我们进一步考虑BC范式,我们可能会发现在这个设计中存在一些函数依赖问题。假设每个部门都有一个负责人,那么我们可以将负责人作为一个新的实体来设计:

员工表
————————————————
| 员工编号 | 姓名 | 部门编号 | 工资 |
————————————————
| 001| 张三| 001 | 5000|
| 002| 李四| 002 | 6000|
| 003| 王五| 003 | 7000|
————————————————

部门表
———————————
| 部门编号 | 部门名称 | 负责人|
———————————
| 001| 技术部| 张三|
| 002| 销售部| 李四|
| 003| 财务部| 王五|
———————————

通过这种设计,我们将部门信息从员工表中分离出来,避免了部门信息的冗余。在部门表中,负责人属性只取决于部门编号,符合BC范式的要求。

这样的设计提高了数据的一致性和完整性,并且减少了冗余数据。根据实际需求和性能要求,我们可以在范式化和反范式化之间做出权衡,选择适合的数据库设计。

总结:

符合三大范式的数据库设计有助于保证数据的一致性、完整性和可维护性,提高查询效率,并节省数据存储空间。然而,在实际应用中,我们需要根据具体的业务需求和性能要求进行权衡,有时也需要适度地进行反范式化设计。