一个设计混乱的数据库就像一个杂乱的房间,用起来非常不方便:东西到处乱放(数据冗余),找件东西要翻遍所有角落(查询困难),扔掉一把旧椅子时,可能会把搭在上面的唯一一件外套也一起扔了(删除异常)。

数据库范式(Normalization) 就是一套“房间整理法则”,指导我们如何合理地组织数据表,以消除冗余、避免上述问题。2NF和3NF是其中最核心、最重要的两条法则。

初始状态:乱糟糟的第一范式 (1NF)

假设我们要设计一个系统来记录学生的选课成绩。最直接的想法可能是把所有信息都塞进一张大表里。这张表符合第一范式(1NF),因为每个单元格都只有一个值,并且没有完全重复的行。但你会发现,它问题重重。

选课成绩表 (符合1NF)

学号课程号学生姓名课程名称授课老师成绩
101CS101张三计算机导论王老师92
101MTH202张三高等数学李老师85
102CS101李四计算机导论王老师88
103PHY301王五量子力学赵老师95

我们先来分析这张表的“身份”信息:

  • 主码 (Primary Key): 要唯一确定一行数据,需要同时知道“哪个学生”和“哪门课”。因为一个学生可以选多门课,一门课也可以被多个学生选。所以,主码是 (学号, 课程号) 这样一个组合。
  • 主属性: 学号, 课程号
  • 非主属性: 学生姓名, 课程名称, 授课老师, 成绩

这张表虽然能用,但有严重的“副作用”(我们称之为“异常”):

  • 更新异常 (Update Anomaly): 如果学生“张三”改名叫“张大三”,你必须修改所有他出现的行。一旦漏掉一行,数据就不一致了。
  • 插入异常 (Insertion Anomaly): 你无法添加一个新生(比如学号104的“赵六”),除非他至少选了一门课。因为主码 (学号, 课程号) 要求 课程号 不能为空。
  • 删除异常 (Deletion Anomaly): 如果“王五”退掉了他唯一选的课(量子力学),那么他所在的整行数据都会被删除。我们不仅丢失了他的选课记录,连“王五”这个学生本身的信息也从数据库里消失了!

如何解决这些问题?答案就是遵循范式法则进行整理。


第一步整理:达到第二范式 (2NF)

2NF的法则

一个表在符合1NF的基础上,如果所有非主属性都“完全函数依赖”于主码,那么它就符合2NF。

  • “完全函数依赖”:听起来很学术,其实很简单。意思就是一个非主属性的值,必须由整个主码来唯一确定,而不是由主码的一部分就能确定。
  • 通俗版法则任何一个非主属性,都不能只依赖于组合主码的一部分。(这条规则只在主码是组合码时才有意义,就像我们这个例子)。
运用2NF法则整理

我们的主码是 (学号, 课程号)。我们来检查一下每个非主属性:

  • 成绩: 由什么决定?必须同时知道 学号课程号 才能确定一个唯一的成绩。所以,成绩 依赖于整个主码这很好,符合2NF。
  • 学生姓名: 由什么决定?只需要 学号 就能确定。学生的姓名和他选了什么课没关系。所以,学生姓名 只依赖于主码的一部分 (学号)。这很糟糕,违反了2NF。
  • 课程名称授课老师: 由什么决定?只需要 课程号 就能确定。这和哪个学生来选课也没关系。所以,这两个属性也只依赖于主码的一部分 (课程号)。这也很糟糕,违反了2NF。
解决方法:拆分!

解决办法就是“分家”。把那些只依赖于部分主码的信息,拆分出去成立自己的独立小家庭(新表)。

  1. 只依赖于 学号 的信息,放到新的 学生表 里。
  2. 只依赖于 课程号 的信息,放到新的 课程表 里。
  3. 依赖于 (学号, 课程号) 完整组合的信息,留在瘦身后的 选课表 里。

学生表 (Students)

学号 (主码)学生姓名
101张三
102李四
103王五

课程表 (Courses)

课程号 (主码)课程名称授课老师
CS101计算机导论王老师
MTH202高等数学李老师
PHY301量子力学赵老师

选课表 (Enrollment)

学号 (外码)课程号 (外码)成绩
101CS10192
101MTH20285
102CS10188
103PHY30195
(这张表的主码依然是 (学号, 课程号))

现在,我们所有的表都符合2NF了,之前提到的那些异常问题也随之解决!张三改名,只需改 学生表 一处。新生赵六可以直接添加到 学生表,不用非得选课。


第二步整理:达到第三范式 (3NF)

我们离完美还差一步。仔细看刚刚创建的 课程表,它里面还隐藏着一个问题。

3NF的法则

一个表在符合2NF的基础上,如果不存在“传递函数依赖”,那么它就符合3NF。

  • “传递函数依赖”:指的是一个非主属性,不直接依赖于主码,而是通过另一个非主属性间接地依赖于主码。形成了一个依赖链条:主码 -> 非主属性A -> 非主属性B
  • 通俗版法则任何一个非主属性,都不能依赖于其他非主属性。
运用3NF法则整理

为了让问题更明显,我们在 课程表 里加一列“老师所在院系”。

课程表 (符合2NF,但不符合3NF)

课程号 (主码)课程名称授课老师老师所在院系
CS101计算机导论王老师计算机系
MTH202高等数学李老师数学系
CS205数据结构王老师计算机系

我们来检查主码 课程号 和非主属性之间的依赖关系:

  • 课程名称 直接依赖于 课程号很好
  • 授课老师 直接依赖于 课程号(为简化,假设一门课只有一个老师)。很好
  • 老师所在院系: 老师的院系是由 课程号 决定的吗?不是! 它是由授课老师决定的。这样就形成了一个依赖链条:
    课程号 -> 授课老师 -> 老师所在院系
    这就是传递依赖,它违反了3NF。

这又会引发老问题!如果“王老师”从“计算机系”调到了“人工智能系”,你就必须修改他教的每一门课的记录,非常麻烦且容易出错。

解决方法:再次拆分!

我们把这个传递依赖链条也拆开,把老师的信息独立出去。

老师表 (Instructors)

授课老师 (主码)老师所在院系
王老师计算机系
李老师数学系
赵老师物理系

新的课程表 (Courses)

课程号 (主码)课程名称授课老师 (外码)
CS101计算机导论王老师
MTH202高等数学李老师
CS205数据结构王老师
PHY301量子力学赵老师

现在,如果王老师调动院系,我们只需在 老师表 中修改唯一的一条记录。至此,我们所有的表都达到了3NF,房间整理完毕!

最终总结

  • 1NF:入场券。 确保数据是“原子的”(每个单元格一个值)。
  • 2NF:消除部分依赖。 确保所有非主属性都依赖于整个组合主码,而不是它的一部分。(解决方法:把依赖于部分的属性拆出去)。
  • 3NF:消除传递依赖。 确保所有非主属性都依赖于主码,而不是依赖于其他非主属性。(解决方法:把间接依赖的属性拆出去)。

通过遵循这些法则,我们把一张庞大、混乱的表,拆分成了四个干净、清晰、健壮的小表:学生表老师表课程表选课表。这就是关系数据库设计的精髓所在。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/diannao/99124.shtml
繁体地址,请注明出处:http://hk.pswp.cn/diannao/99124.shtml
英文地址,请注明出处:http://en.pswp.cn/diannao/99124.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

数据结构---循环队列

基于循环数组实现的循环队列解决了顺序队列中的假溢出导致的空间浪费问题操作:(1)初始化//循环队列 typedef struct {int *data;//指针模拟声明数组int head,tail;//队头,队尾 }Queue; //初始化 Queue *InitQueue() {Queue *q (Q…

深入理解线程模型

线程作为操作系统调度的基本执行单元,是实现高吞吐、低延迟系统的基础。一、进程与线程的体系结构对比核心概念:进程(Process):操作系统资源分配的基本单位,拥有独立的虚拟地址空间、文件描述符表、环境变量…

TTC定时器中断——MPSOC实战3

开启TTC定时器&#xff0c;不同于7000系列的私有定时器此处设置LPD_LSBUS频率TTC频率取决于LPD_LSBUS可前往指定位置查看参数不使能填写对应宏可前往指定位置查看参数main.c#include <stdio.h> #include "xparameters.h" #include "xgpiops.h" #incl…

人工智能训练师三级备考笔记

一、实操1&#xff09;通用语法&#xff08;常见于实操题第一块代码块&#xff09;1.读取文件数据或加载数据集等描述时一般为以下结构&#xff1a;Datapd.read_文件格式(文件名) 注意&#xff1a;文件名需要用‘ ’框起来&#xff0c;必须要有引号文件格式有以下内容csv、txt…

Cherry Studio递归工具调用机制深度解析

在现代AI应用开发中,工具调用(Tool Calling)已成为大语言模型与外部系统交互的核心机制。Cherry Studio作为一款先进的AI对话客户端,实现了一套完整的递归工具调用系统,能够让AI助手在执行复杂任务时自动调用多个工具,并根据执行结果智能决策下一步操作。本文将深入解析这…

[哈希表]966. 元音拼写检查器

966. 元音拼写检查器 class Solution:def spellchecker(self, wordlist: List[str], queries: List[str]) -> List[str]:origin set(wordlist) # 存储原始单词用于完全匹配lower_to_origin {} # 存储小写形式到原始单词的映射vowel_to_origin {} # 存储元音模糊形…

正则表达式与文本三剑客(grep、sed、awk)基础与实践

正则表达式基础与实践一、正则表达式概述1. 定义正则表达式&#xff08;Regular Expression&#xff0c;简称 RE&#xff09;是用于描述字符排列和匹配模式的语法规则&#xff0c;核心作用是对字符串进行分割、匹配、查找、替换操作。它本质是 “模式模板”&#xff0c;Linux 工…

eclipse中web项目编译后的lib里面jar为空问题处理

1. 检查项目构建配置验证项目性质右键单击项目 → Properties确认项目已正确配置&#xff1a;​Project Facets​&#xff1a;确保已勾选"Dynamic Web Module"​Targeted Runtimes​&#xff1a;确保已选择服务器运行时&#xff08;如Tomcat&#xff09;检查部署程序…

C语言中的递归问题——汉诺塔问题

汉诺塔&#xff08;Tower of Hanoi)&#xff0c;又称河内塔&#xff0c;是一个源于印度古老传说的益智玩具。传说大梵天创造世界的时候做了三根金刚石柱子&#xff0c;在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘。大梵天命令婆罗门把圆盘从下面开始按大小顺序重新摆放在…

ArkAnalyzer源码初步分析I——分析ts项目流程

1.前言&#xff1a; 鸿蒙程序分析框架ArkAnalyzer&#xff08;方舟分析器&#xff09; 源码地址 入门文档 2.阅读入门文档后&#xff1a; 本人具有一定的Java开发经验。虽然我对 TypeScript&#xff08;TS&#xff09;和 ArkTS 还不熟&#xff0c;但很多概念对我这个 Java 开…

c#基础二(类和对象,构造器调用顺序、访问级别、重写和多态、抽象类和接口)

一、类1.0对象初始化器class Student {public String name;public int age { get; set; } } internal class Program {static void Main(string[] args){ //写法一Student stunew Student();stu.name"Tom";stu.age20;//写法二Student stu2 new Student { name &qu…

Qt之快捷键、事件处理、自定义按键——完成记事本项目

快捷键我们电脑中的记事本中还支持快捷键&#xff0c;如“CTRLO”打开文件、“CTRLS”保存文件在Qt中使用QShortcut这个类创建快捷键在.cpp文件的构造函数中创建QShortcut对象&#xff0c;绑定打开文件和保存文件的槽函数放大缩小字体还是在.cpp的构造函数中编写代码Widget::Wi…

Open cascade中如何使用BRepAlgoAPI_Splitter分割一个Face

理论介绍 在OpenCASCADE几何建模内核中&#xff0c;BRepAlgoAPI_Splitter是一个强大的工具&#xff0c;用于将一个形状&#xff08;Shape&#xff09;用另一个形状&#xff08;Tool&#xff09;进行分割。这种操作在CAD建模中非常常见&#xff0c;比如用平面切割实体、用曲线分…

【医疗 AI】Baichuan-M2 医疗大模型:技术解读与使用方法

【医疗 AI】Baichuan-M2 医疗大模型&#xff1a;技术解读与使用方法1. Baichuan-M2 医疗大模型简介1.1 基本信息1.2 下载地址1.3 技术特点2. Baichuan-M2 模型技术报告2.1 摘要2.2 医学性能评估2.2.1 HealthBench基准2.2.2 中国医疗场景对比评估2.3 系统架构2.3.1 验证器系统2.…

unity pcd 二进制版 简单显示文件对象(单色)

unity Point Cloud Viewer and Tool 那个插件不支持pcd二进制&#xff0c;而且网上到处都是AI 我恨这种AI滥用&#xff0c;提供不了一点价值 好了&#xff0c;言归正传 可以在Point Cloud Viewer and Tool这个插件报错地方转用这个代码&#xff0c;具体咋结合请自行研究。 …

强大的开源文档问答工具-Kotaemon

Kotaemon 是一个基于 RAG&#xff08;Retrieval-Augmented Generation&#xff09;架构的开源文档问答工具&#xff0c;为用户提供与文档对话的智能交互体验。该项目同时服务于终端用户和开发者&#xff0c;具有高度的可扩展性和定制化能力。技术栈分析核心技术栈后端框架Pytho…

区块链:搭建简单Fabric网络并调用智能合约

使用docker服务搭建Hyperledger/fabric网络的详细教程&#xff0c;实现构建多节点的简单联盟链&#xff0c;并编写、调用智能合约实现投票业务。 目录 背景知识 Hyperledger Fabric 基本组件 交易(Transaction) 智能合约 实验目的 实验环境 基础依赖 安装Golang 安装do…

Web前端面试题(2)

Web前端面试题(附答案及解析)&#xff08;2025.9月最新版&#xff09;-CSDN博客 1.link 与 import 的区别和用法 主要区别 特性<link>import语法类型HTML标签CSS规则加载方式并行加载&#xff08;与其他资源同时加载&#xff09;串行加载&#xff08;必须等待主CSS文件…

Paxos协议

目录 Paxos 是什么&#xff08;What&#xff09; Paxos 的目的&#xff08;Why&#xff09; 角色与职责&#xff08;Who&#xff09; 基本流程&#xff08;How&#xff09; 常见问题与对策 什么是多数派&#xff08;Quorum&#xff09; Paxos vs Raft 异同点 Paxos 是什…

第十二篇:Qcom Camx打印实时帧率 FPS

一、第一种方式(有些低平台可能没有) adb shell setprop persist.vendor.camera.enableFPSLog TRUE adb shell setprop persist.vendor.camera.systemLogEnable TRUE adb shell setprop vendor.debug.camera.overrideLogLevels 0xff chi-cdk/core/chiframework/chxextensi…