数据库范式(详细介绍)
目录
第一范式(原子性
)
确保每列保证
原子性
,保证这个属性(字段)不能在被分割。不符合第一范式:
订单
--------------------------------------------------------------
| 订单编号 | 产品名称 ? ? ? | 产品价格 ? ? ? ? ?|
--------------------------------------------------------------
| 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范式的要求。
这样的设计提高了数据的一致性和完整性,并且减少了冗余数据。根据实际需求和性能要求,我们可以在范式化和反范式化之间做出权衡,选择适合的数据库设计。
总结:
符合三大范式的数据库设计有助于保证数据的一致性、完整性和可维护性,提高查询效率,并节省数据存储空间。然而,在实际应用中,我们需要根据具体的业务需求和性能要求进行权衡,有时也需要适度地进行反范式化设计。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!