高级java每日一道面试题-2024年8月30日-数据库篇-数据库的三范式是什么?
如果有遗漏,评论区告诉我进行补充
面试官: 数据库的三范式是什么?
我回答:
在数据库设计中,范式(Normalization)是一种设计准则,用于指导如何有效地组织数据库中的数据,以减少数据冗余和提高数据完整性。其中,最为基础和重要的是前三个范式(1NF, 2NF, 3NF),它们为数据库设计提供了重要的指导原则。下面是对这三个范式的详细解释:
1. 第一范式(1NF - First Normal Form)
定义:数据库表的每一列都是不可分割的基本数据项,同一列中不能有多个值,即实体中的某个属性不能有多个值或者不能有重复的属性。简而言之,第一范式要求表中的所有字段值都是原子的,不可再分的。
目的:确保每列保持原子性,以便于数据的维护和一致性。
示例1:假设有一个关于员工的表,如果有一个字段是“联系电话”,那么该字段应该只包含一个电话号码,而不是多个电话号码的列表。如果需要存储多个电话号码,则应该将其拆分为另一个表,并通过某种关系与原表关联。
示例2:如果有一个表用来记录学生的选课情况,那么这个表应该只包含单个学生的信息,而不是一组学生的信息。例如,不应该有这样一行数据:
- 学生姓名: 张三, 李四
- 课程编号: CS101
而应该拆分为两行: - 学生姓名: 张三, 课程编号: CS101
- 学生姓名: 李四, 课程编号: CS101
2. 第二范式(2NF - Second Normal Form)
定义:在满足第一范式的基础上,非主属性完全依赖于候选键(即表中的所有非主属性都完全依赖于表的任何一个候选键)。如果一个表有多个候选键,则非主属性不能仅依赖于候选键的一部分。
目的:消除部分依赖,确保表中的每一行都与主键有完整的关系,从而减少数据冗余和提高数据的一致性。
示例1:假设有一个订单表,包含订单ID、订单日期、客户ID、客户姓名和订单金额。如果订单ID是主键,但客户姓名也依赖于客户ID,则客户姓名就部分依赖于订单ID(因为订单ID并不直接决定客户姓名,而是通过客户ID间接决定)。为了符合第二范式,应该将客户ID和客户姓名移到一个单独的表中,并通过客户ID与订单表关联。
示例2:如果有一个学生选课表,其中包含多个字段:学生姓名、学号、班级编号、课程编号。假设主键是(学号, 课程编号),则所有非主键字段都应该依赖于完整的主键组合。
如果存在以下情况:
- 学生姓名: 张三
- 学号: 123456
- 班级编号: B01
- 课程编号: CS101
这里,班级编号只依赖于学号,而不是完整的主键(学号, 课程编号),这是不符合2NF的。要使其符合2NF,我们需要将班级编号移动到另一个表中,该表仅包含学号和班级编号。
3. 第三范式(3NF - Third Normal Form)
定义:在满足第二范式的基础上,消除传递依赖。即表中的每一列都直接依赖于主键,而不是通过其他非主键列间接依赖。
目的:进一步减少数据冗余和依赖,提高数据表的独立性和可维护性。
示例1:继续上面的订单表例子,如果订单表中还包含了订单所在的仓库名称,且仓库名称是通过订单中的某个字段(如订单类型或产品类型)间接与订单ID关联的,则仓库名称就存在传递依赖。为了符合第三范式,应该将仓库名称移到另一个表中,并通过相应的关系与订单表关联。
示例2:如果有一个学生表,其中包含学生的姓名、地址和电话号码,假设地址和电话号码之间存在关联(即电话号码是根据地址查询得到的),那么电话号码就不是直接依赖于主键(学生ID),而是依赖于地址。这会导致数据冗余和不一致的问题。
- 为了达到3NF,我们需要将电话号码存储在一个单独的表中,这个表只包含地址和电话号码,而学生表中只保留学生ID和地址。
- 遵循三范式可以帮助我们设计出更合理、更高效的关系型数据库结构,减少数据冗余,保证数据的一致性。然而,在实际应用中,有时为了提高查询性能或其他考虑,可能会选择适当违反三范式,但这需要仔细权衡利弊。
总的来说,数据库的三范式是数据库设计的重要指导原则,它们通过减少数据冗余和提高数据完整性,来帮助我们设计出更加高效、可靠的数据库系统。