数据库范式是一种规范化数据结构的方式,用于设计数据库模式和关系模式。现在,从第一范式到第五范式已经成为了广泛应用的数据库范式规范。在本文中,我们将深入探讨这些范式的概念和原则,以及它们如何应用于数据库设计中。
从第一范式(1NF)开始
第一范式是在1960年左右被开发出来的。它主要是用于规范化 relation(关系)(在如今的数据库理论中也称作表)中的属性,从而避免重复数据和冗余数据的存在。在第一范式中,关系中的每一列都必须是原子性的,也就是说每一列的数据只能是不可再分的最小单位,不能再进行细分。
第一范式的实现可以通过将每个属性独立为一个单独的列来实现。示例如下:
用户ID | 用户名 | 电子邮件地址 | 电话号码
这个示例是一个用户表,为了符合第一范式,每个属性被独立为一个单独的列。这种设计的好处是可以避免属性间的数据冗余。
第二范式(2NF)的实现
第二范式出现在1971年之后,它是继第一范式之后的一个扩展。第二范式的目的是保证在一个表中每个非键属性都依赖于该表中的一个主键,而不是部分依赖于主键。也就是说,第二范式强制每个表只处理单个主题或实体,这保证了查询的单一性。
例如,下面这个表就不符合第二范式:
用户ID | 用户名 | 邮箱地址 | 城市 | 省份
因为城市和省份这两个非键属性部分依赖于用户ID和用户名,它存在部分依赖的情况。一个更好的解决方案是将这个表拆分成两张表,其中一张表存储用户的基本信息,而另一张表则存储城市和省份的信息,并通过外键进行连接。
第三范式(3NF):消除传递依赖
第三范式强制表中的每个非主键列只能通过主键列进行依赖,而不是依赖于其他非主键列。也就是说,如果每个属性只依赖于关系的主键,则该关系符合第三范式。
例如:
订单ID | 顾客ID | 顾客名 | 产品ID | 产品名 | 产品价格
在这里,非主键属性产品名和产品价格不仅依赖于产品ID,还依赖于订单ID,因此存在传递依赖的情况。为了符合第三范式,应该将产品名和产品价格拆分为另一张表,以避免传递依赖存在。
BCNF:消除合成依赖
BCNF是指Boyce-Codd范式,1995年由R. Fagin等人提出,目的是消除依赖于主键的合成依赖。什么是合成依赖呢?就是说,如果仅仅是主键的一部分成为了非主键属性的一部分,而该非主键属性又被其他非主键属性依赖的话,就是合成依赖。
例如:
订单ID | 顾客名 | 产品名 | 产品价格
在这个表中,订单ID 和 顾客名 合成为主键,而非主键属性 产品名和产品价格 却只依赖于顾客名,这也违反了BCNF。因此,应该将顾客名拆分为另一张表,从而消除合成依赖。
第四范式(4NF):消除多值依赖
第四范式在1982年被E.F. Codd提出,主要是用于规范化多值依赖关系。什么是多值依赖呢?就是关系模式中某一个非主属性对于某一个联合主键不能唯一确定,只能通过联合主键的子集进行确定。
例如:
用户ID | 电话号码 | Email地址
在这个表中,一个用户可能会有多个电话号码和多个邮箱地址,这就是多值依赖。为了避免这种情况,可以将电话号码和邮箱地址分别存储在单独的表中,每个表的主键都是用户ID,例如:
用户ID | 电话号码
用户ID | Email地址
第五范式(5NF):消除循环依赖
第五范式也称作投影完备依赖,是在1994年被R. Fagin提出的。它是指一个关系中所有关系类型的子集都有一个完备的函数依赖关系(functional dependency)。也就是说,如果表中的数据被分为多个表,然后在重新组合这些表时,仍然可以得到完整的数据。
例如:
家谱表
人物 | 祖先1 | 祖先2
在这张表中,每个人物可以有多个祖先,这就导致了循环依赖的情况。为了符合第五范式,可以将每个祖先单独存储在一个表中,并使用外键将它们连接起来。
总结
以上就是从第一范式到第五范式的解析,通过遵循这些范式的规则和原则,我们可以创建出高效和灵活的数据库模式和关系模式,从而实现更好的数据存储和检索。当然,这些范式并不是规范化设计的终点,有时候在某些情况下,我们也可以根据实际需求灵活地应用它们,以实现更合适的数据库设计。