目录
第一范式(原子性)
第二范式(主键唯一性)
第三范式(原子性+主键唯一性)
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),因为有部分字段依赖于订单号,而另一部分字段依赖于顾客姓名。这样的表结构存在以下问题:
数据冗余:同一个顾客的姓名和地址信息重复出现,会导致数据冗余,增加了存储空间的消耗。
更新异常:如果需要更新顾客的地址,那么就需要同时更新多条记录,容易出现更新异常,导致数据不一致。
第三范式(原子性+主键唯一性)
第三范式在第二范式的基础之上,消除了非主属性对于码的
传递函数依赖
。就是说任何非主属性不依赖于其它非主属性。一个不符合第三范式(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 |
-------------------------------------------------在这个例子中,可以看到存在以下问题:
数据冗余:同一个供应商的名称和地址信息重复出现,会导致数据冗余,增加了存储空间的消耗。
更新异常:如果需要更新某个供应商的地址,那么就需要同时更新多条记录,容易出现更新异常,导致数据不一致。
为了符合第三范式,我们可以将上述表拆分成两个表:
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范式要求:
每个非主属性都完全依赖于候选键。也就是说,如果一个属性只依赖于候选键的一部分而不是全部,那么它就不符合BC范式。
所有的函数依赖都应该是候选键的超键。也就是说,任何非候选键的属性都不应该决定其他非候选键的属性。
BC范式的目标是消除数据冗余,并且确保数据的一致性和完整性。通过将关系数据库设计满足BC范式,可以提高数据库的性能和可维护性。
需要注意的是,BC范式是对关系数据库设计的理论指导,并不是必须遵守的绝对规则。在某些情况下,根据实际需求和性能考虑,可能需要在范式化和反范式化之间做出权衡。
举个例子:假设我们有一个关系数据库用于存储员工信息,包含以下字段:员工编号、姓名、部门、工资。
员工编号是主键(候选键),每个员工的编号唯一标识其身份。
姓名、部门和工资都完全依赖于员工编号。
在第三范式(3NF)下,我们可以将数据设计如下:
员工表 ------------------------------------------------ | 员工编号 | 姓名 | 部门 | 工资 | ------------------------------------------------ | 001 | 张三 | 技术部 | 5000 | | 002 | 李四 | 销售部 | 6000 | | 003 | 王五 | 财务部 | 7000 | ------------------------------------------------
这个设计符合第三范式(3NF),因为每个非主属性(姓名、部门、工资)都完全依赖于候选键(员工编号),没有冗余数据。
然而,如果我们进一步考虑BC范式,我们可能会发现在这个设计中存在一些函数依赖问题。假设每个部门都有一个负责人,那么我们可以将负责人作为一个新的实体来设计:
员工表
------------------------------------------------
| 员工编号 | 姓名 | 部门编号 | 工资 |
------------------------------------------------
| 001 | 张三 | 001 | 5000 |
| 002 | 李四 | 002 | 6000 |
| 003 | 王五 | 003 | 7000 |
------------------------------------------------部门表
---------------------------------
| 部门编号 | 部门名称 | 负责人 |
---------------------------------
| 001 | 技术部 | 张三 |
| 002 | 销售部 | 李四 |
| 003 | 财务部 | 王五 |
---------------------------------
通过这种设计,我们将部门信息从员工表中分离出来,避免了部门信息的冗余。在部门表中,负责人属性只取决于部门编号,符合BC范式的要求。
这样的设计提高了数据的一致性和完整性,并且减少了冗余数据。根据实际需求和性能要求,我们可以在范式化和反范式化之间做出权衡,选择适合的数据库设计。
总结:
符合三大范式的数据库设计有助于保证数据的一致性、完整性和可维护性,提高查询效率,并节省数据存储空间。然而,在实际应用中,我们需要根据具体的业务需求和性能要求进行权衡,有时也需要适度地进行反范式化设计。