当前位置: 首页 > article >正文

高级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和地址。
  • 遵循三范式可以帮助我们设计出更合理、更高效的关系型数据库结构,减少数据冗余,保证数据的一致性。然而,在实际应用中,有时为了提高查询性能或其他考虑,可能会选择适当违反三范式,但这需要仔细权衡利弊。

总的来说,数据库的三范式是数据库设计的重要指导原则,它们通过减少数据冗余和提高数据完整性,来帮助我们设计出更加高效、可靠的数据库系统。


http://www.kler.cn/a/283783.html

相关文章:

  • HTTP 客户端怎么向 Spring Cloud Sleuth 传输跟踪 ID
  • Ruby编程语言全景解析:从基础到进阶
  • python 同时控制多部手机
  • Window下PHP安装最新sg11(php5.3-php8.3)
  • uniCloud云对象调用第三方接口,根据IP获取用户归属地的免费API接口,亲测可用
  • LabVIEW开发相机与显微镜自动对焦功能
  • Java技术栈 —— Spark入门(三)之实时视频流
  • Dubbo如何传递链路追踪id?
  • 小琳AI课堂:使用ChatGPT API搭建系统(二)
  • innovus:如何让部分sink长到target insertion delay的长度
  • 关于OBI 在unity URP环境下使用的正确步骤
  • 网络编程(学习)2024.8.27
  • jQuery基础——选择器的补充方法——过滤方法、查找方法
  • python使用multiprocessing多进程通讯
  • 各种各样的正则表达式
  • 92. UE5 RPG 使用C++创建GE实现灼烧的负面效果
  • 达梦数据库-DM8 企业版安装指南
  • [java][代码] java中date格式化输出时间字符串
  • 《征服数据结构》LFU缓存
  • Vatee万腾平台:打造企业智能化转型的坚实后盾
  • 【Android】UIMode
  • fpga图像处理实战-双三次插值算法
  • Jmeter提取token并设置为全局变量
  • 聊聊STM32 MCU的BOOT0和BOOT1引脚
  • 浅谈Vue3和React18
  • 六个方面探讨企业为何迫切需要替换FTP