此文章以例题为主线,讲解题中数据库系统概论的知识点,没学过数据库概论的同学也可以进行学习。如果想要更牢固的掌握知识点,可以先学习数据库设计基础知识。
💬 欢迎讨论:如对文章内容有疑问或见解,欢迎在评论区留言,我需要您的帮助!
👍 点赞、收藏与分享:如果这篇文章对您有所帮助,请不吝点赞、收藏或分享,谢谢您的支持!
🚀 传播技术之美:期待您将这篇文章推荐给更多对需要学习数据库系统概论、低代码开发感兴趣的朋友,让我们共同学习、成长!
1. 码和属性
1.1 例1
1.1.1 补充知识点
函数依赖、传递函数依赖、候选码、主属性和非主属性
(1)
函数依赖
在关系数据库中,函数依赖是指一个关系模式(可以简单理解为一张表)中属性之间的一种约束关系。如果给定一个属性(或属性组)的值,就能够唯一确定另一个属性(或属性组)的值,那么就称后者函数依赖于前者。
这是一个学生成绩表格,Sno是学号,Cno是课程号,Grade表示成绩。
Sno | Cno | Grade |
---|---|---|
001 | C01 | 85 |
001 | C02 | 90 |
002 | C01 | 78 |
从该表中可以看出(Sno,Cno)一起能决定成绩Grade。称为Grade
完全依赖于Sno
和Cno
(2)
传递函数依赖
系表:
Deptno | Dname |
---|---|
001 | 计算机系 |
002 | 数学系 |
老师表:
Tno | Tname | Deptno | Director |
---|---|---|---|
0001 | 张老师 | 001 | 李主任 |
0002 | 王老师 | 001 | 李主任 |
0003 | 赵老师 | 002 | 钱主任 |
系号确定系主任
所以,Tno
对Director
是传递函数依赖,
(3)
候选码:候选码是能够唯一标识关系中每一个元组的最小属性集。一个关系可能有多个候选码,这些候选码都具有能够唯一标识元组的能力,并且不能再减少其中的属性而仍然保持唯一性。
举例:
假设在一个员工信息表中有员工编号、身份证号、姓名、部门编号
这几个属性。员工编号和身份证号都可以唯一地标识一个员工。因为任何一个员工都有唯一的员工编号和唯一的身份证号。这里员工编号和身份证号就是候选码。姓名可能会有重复,不能单独作为候选码;部门编号也不能单独标识一个员工,因为一个部门有多个员工。
员工编号 | 身份证号 | 姓名 | 部门编号 |
---|---|---|---|
001 | 110101199001011234 | 张三 | 101 |
002 | 110102199203025678 | 李四 | 102 |
003 | 110103198805058910 | 王五 | 101 |
再比如一个课程表,包含课程号、课程名称、授课教师姓名这几个属性。如果规定课程号是唯一的,并且课程名称和授课教师姓名组合起来也是唯一的(即不会出现两门课程有相同的课程名称和相同的授课教师),那么课程号和(课程名称,授课教师姓名)这两组属性都是候选码。
(4)
主属性:包含在任何一个候选码中的属性称为主属性。
非主属性:关系模式中除了主属性之外的属性就是非主属性。
举例说明:
假设有一个关系模式R(学号,姓名,性别,班级,班主任)
学号 | 姓名 | 性别 | 班级 | 班主任 |
---|---|---|---|---|
12345678 | 陈宇 | 男 | 一班 | 张老师 |
87654321 | 林悦 | 女 | 二班 | 李老师 |
56781234 | 王浩 | 男 | 三班 | 王老师 |
34567890 | 刘萱 | 女 | 四班 | 赵老师 |
98765432 | 孙阳 | 男 | 一班 | 张老师 |
假设在这个学校里,学号是唯一的,学号可以唯一确定一个学生的所有信息(姓名、性别、班级、班主任),那么学号就是一个候选码。
同时,姓名和班级组合起来也能唯一确定一个学生(假设学校里不存在姓名相同且班级相同的两个学生),那么(姓名,班级)也是一个候选码。
在这个例子中,学号、姓名和班级都是主属性,因为它们分别包含在候选码(学号)和候选码(姓名,班级)中。而性别和班主任不是主属性,因为它们没有参与构成候选码。
1.2.2 题
关系模式:
教师(教师号,教师姓名,系别,系主任,课程,班级)
规定:
一个教师只能在一个系工作
每个系有一个系主任
教师可以教授多门课程,课程可以有多个教师教授
每个教师的每门课程对应一个班级
问题: 分析候选码,主属性,非主属性
1.1.3 解题
分析:
由于 “一个教师只能在一个系工作”,意味着教师号可以确定教师所在的系别;“每个系有一个系主任”,系别又能确定系主任;“教师可以教授多门课程,课程可以有多个教师教授”,说明仅靠教师号不能确定课程;“每个教师的每门课程对应一个班级”,也就是教师号和课程组合起来才能确定对应的班级。
整理出的函数依赖为:
系–>系主任
教师号–>系
(教师号,课程)–>班级
综合来看,教师号和课程的组合(教师号,课程)能够唯一确定该关系模式中的每一个元组,并且不存在其真子集(单独的教师号或者单独的课程)能做到这一点,所以(教师号,课程)是候选码。
包含在候选码中的属性就是主属性,所以教师号和课程是主属性。
关系模式中除了主属性之外的属性就是非主属性,在这里教师姓名、系别、系主任、班级就是非主属性。
答:
候选码:(教师,课程)
主属性:教师号和课程
非主属性:教师姓名、系别、系主任、班级
1.2 例2
学生(学号,姓名,班级号,性别)
班级(班级号,班级名称,人数)
分析每个关系模式的主码以及是否含有外码
分析:
(1)学生关系模式
学号在学生群体中通常是唯一的,能够唯一标识每一个学生,所以学号是学生关系模式的主码。
班级号出现在学生关系模式中,它参照了班级关系模式中的班级号(班级关系模式中班级号是主码),用于表明学生所属的班级,所以班级号是学生关系模式中的外码。
(2)班级关系模式
班级号能够唯一区分不同的班级,所以班级号是班级关系模式的主码。
该关系模式中不存在参照其他关系模式主码的属性,所以没有外码。
答:
在学生关系模式中,主码是学号,外码是班级号;
在班级关系模式中,主码是班级号,无外码。
2. E-R图
2.1 例题1
2.1.1 知识点补充
两个实体之间的联系、两个以上实体之间的联系、 单个实体内的一对多联系
(1)
两实体之间的联系
- 一对一联系(1:1)
- 一对多联系(1:n)
- 多对多联系(m:n)
E-R模型:
(2)
两个以上实体 型之间的联系
一般地,两个以上的实体型之间也存在着一对一、一对多、多对多的联系
比如:对于课程、教师与参考书3个实体型,如果一门课程可以有若干个教师讲授,使用若干本参考书,而每一个教师只讲授一门课程,每一本参考书只供一门课程使用,则课程与教师、参考书之间的联系是一对多的,如图
比如:对于供应商、项目、零件
(3)
单个实体内的一对多联系
比如:一个职工只能有一个直属领导,而一个领导能管理很多个职工,职工和领导都是职工。
2.1.2 题
某个工厂物资管理的概念模型。物资管理涉及的实体有:
(1)仓库:属性有仓库号、面积、电话号码
(2)零件:属性有零件号、名称、规格、单价、描述
(3)供应商:属性有供应商号、姓名、地址、电话号码、账号
(4)项目:属性有项目号、预算、开工日期
(5)职工:属性有职工号、姓名、年龄、职称这些实体之间的联系如下:
(1)一个仓库可以存放多种零件,一种零件可以存放在多个仓库中,因此仓库和零件具有多对多的联系。用库存量来表示某种零件在某个仓库中的数量。
(2)一个仓库有多个职工当仓库保管员,一个职工只能在个仓库工作,因此仓库和职工之间是一对多的联系。
(3)职工之间具有领导与被领导关系。即仓库主任领导若干保管员,因此职工实体型中具有一对多的联系。
(4)供应商、项目和零件三者之间具有多对多的联系。即一个供应商可以供给若干项目多种零件,每个项目可以使用不同供应商供应的零件,每种零件可由不同供应商供给。
2.1.3 解题
分析:
实体属性:
(1)“仓库” 实体的 “仓库号”“面积”“电话号码” 属性对应的椭圆形,分别用线段连接到 “仓库” 矩形框上。
(2)“零件” 实体的 “零件号”“名称”“规格”“单价”“描述” 属性对应的椭圆形连接到 “零件” 矩形框。
(3)“供应商” 实体的 “供应商号”“姓名”“地址”“电话号码”“账号” 属性椭圆形与 “供应商” 矩形框相连。
(4)“项目” 实体的 “项目号”“预算”“开工日期” 属性椭圆形和 “项目” 矩形框连接。
(5)“职工” 实体的 “职工号”“姓名”“年龄”“职称” 属性椭圆形与 “职工” 矩形框连接。
实体及其联系:
仓库与零件的多对多关系;
仓库与职工的一对多关系;
职工之间的一对多领导关系;
供应商零件之间的多对多关系;
供应商和项目之间的多对多关系。
答:
实体属性图和实体联系图合并:
3. 函数依赖和范式
3.1 例题
3.1.1 知识点补充
范式的概念、1NF、2NF、3Nf
(1)
什么是范式?
答:
范式(Normal Forms,简称 NF)是关系数据库设计中的一系列规则,用于确保数据库结构的合理性,减少数据冗余,并避免数据操作时出现异常(如插入异常、删除异常和更新异常)。
为什么要规定范式?
答:
便于理解;减少数据冗余,当数据库不遵循范式时,数据可能会大量重复存储;避免数据操作异常,如不遵循范式,可能会出现插入数据困难的情况;提高数据的一致性和完整性,范式有助于确保数据在整个数据库中的一致性。
那我们如何确定冗余的数据可能会进入表中?
事实证明,我们可以使用一组标准来评估危险程度
我们可以将这些规范行式类比为安全评估
假如我们对桥的评估为:
安全等级1:适用于行人交通。
安全等级2:适用于轿车交通。
安全等级3:适用于卡车交通。
以此类比,第一范式(1NF)就是对数据库设计最基本的等级评估。
(2)
第一范式 1NF
下面的表格看着舒服吗?其实更像一个文本。第一范式规定,不允许使用行顺序传达信息。
同学们可以看一下下面的表格,信息很全,但是很乱,这就不符合第一范式,第一范式规定,不允许在同一列中混合不同的数据类型。
加入我们正在设计一个在线多人游戏的数据库,某个时间点,每个玩家都拥有很多种类的物品,比如剑、盾牌和铜币;大致如下
如果我们想知道哪些玩家拥有超过10铜币,上面设计的文本表格很不容易查询。可以把表格设计为以下方式:
每个表格都作为一个专属物件的厂库。但是玩家会有几百个种类的装备,创建一个超宽的表来查询还是非常笨拙。我们还可以这样设计:
把前两列作为主键,该表格表示为:
玩家jdog的amulets的装备数量为2;
玩家trev73的shields的装备数量为3;
玩家trev73的arrows的装备数量为5。
总结
第一范式,也就是表的基本要求:
- 不允许使用行顺序传达信息。
- 不允许在同一列中混合不同的数据类型。
- 不允许没有主键的表。
- 不允许重复组。
(3)
第二范式 2NF
第一范式的表看起来是规范的,但是假设我们稍微增加一下表。
假设每个玩家都有一个等级:初学者、中级或高级
为了实现这一点,我们需要再增加一列Player_Rating
显而易见,相同的玩家有几行,该玩家的等级就会出现相应的次数。
这是一个不好的设计,为什么呢?
假设gila19
失去了她说所有的铜币,这会使得她的库存为空,即改行就会消失。
gila19
就无法再被访问了,这个玩家还存在,但是数据库中没有他的信息了,这是矛盾的。
假如,玩家jdog
升级了,就会变成Advance
,但是他的多行存在可能会遗漏更改,这也是一个巨大的问题。
玩家jdog21
在该表中会出现两个等级,这是不合理的。
所以我们要设计第二范式,第二范式涉及表的非主键列和主键的关系
重新看一下这个表:
该表的主键是:(Player_ID,Item_typpe)
,列Item_Quantity
完全依赖于主键(Player_ID,Item_typpe)
,而列Player_Rating
依赖于主键:(Player_ID,Item_typpe)
中的Player_ID
第二范式规定非键属性必须依赖于整个主键。
所以,Player_Rating
不能放入上表中,需要
对Player_ID
和Player_Rating
重新创建一个表。
总结:
第二范式,非主键列和主键的关系:
- 非键属性必须依赖于整个主键
(4)
第三范式 3NF
上述的表不易足够存储一个玩家的数据,我们还需要添加一个名为Player_Skill_Level
的列。
假设技能级别有1-9的分制,分别表示一个玩家的熟练程度,1-3为初级,4-6为中级,7-9为高级
表格如下:
当一个玩家不断地练习时,他的等级就会慢慢的升高,如果玩家gila19
等级升为4
时,她的Player_Rating
应该升级为Intermadiate
。但假设出现错误,未能更新Player_Rating
,现在的数据就会不一致。
gila19
的Player_Rating
显示她是初级,而Player_Skill_Level
显示她是中级,这是矛盾的。
从第二范式来看,Player_Rating
和Player_Skill_Level
都完全依赖于Player_ID
,并没有什么不合适的,但是实际上很不合适。
他们的依赖关系如下:
这样的关系被称为传递依赖。非键属性依赖于非键属性是不合理的。
这时需要改进该表格,把Player_Rating
从上面的表格中移除,重新与Player_Skill_Level
在另一个表格中建立关系。如下:
总结:
第三范式,非主键列和非主键列的关系
- 非主键列不能存在传递函数依赖关系。
- 每个非主键属性都必须依赖于键(整个建或单单键)
3.1.2 题
设有关系模式R(职工编号,日期,日营业额,部门名,部门经理),该模式用于统计商店里每个职工的日营业额以及职工所在的部门信息和经理信息。如果规定:每个职工每天只有一个营业额;每个职工只在一个部门工作;每个部门只有一个经理。
试回答以下问题:
(1)根据上述规定,写出关系模式R的基本函数依赖和候选码。
(2)R是不是2NF?如果不是,请说明R不是2NF的理由,并将其分解成2NF模式集。
(3)进而分解成3NF模式集
3.1.3 解题
分析:
(1)
函数依赖为:
(职工编号,日期)–> 日营业额
职工编号 --> 部门名
部门名 --> 部门经理
根据上述的函数依赖可以推出,(职工编号,日期)是候选码
(2)
第二范式规定,非键属性必须依赖于整个主键,通过函数依赖可以看到,部门名和部门经理不是完全依赖于(职工编号,日期),所以不符合第二范式。
修改后:
R1(职工编号,日期,日营业额):在这个关系模式中,(职工编号,日期)是候选码,日营业额完全函数依赖于(职工编号,日期),满足 2NF 的要求。
R2(职工编号,部门名,部门经理):这里职工编号是候选码,部门名完全函数依赖于职工编号,部门经理完全函数依赖于职工编号,也满足 2NF 要求。
(3)
第三范式规定:非主键列不能存在传递函数依赖关系;每个非主键属性都必须依赖于键(整个建或单单键)。
R2(职工编号,部门名,部门经理),部门经理是传递性依赖函数,所以不符合第三范式。
修改后:
R1(职工编号,日期,日营业额):在这个关系模式中,(职工编号,日期)是候选码,日营业额完全函数依赖于(职工编号,日期),满足 3NF 的要求。
R2(职工编号,部门名,部门经理):这里职工编号是候选码,部门名完全函数依赖于职工编号,也满足 3NF 要求。
R2(部门名,部门经理):这里部门名是候选码,部门经理完全函数依赖于部门名,也满足 3NF 要求。
答:
(1)
基本函数依赖为:
(职工编号,日期)–> 日营业额
职工编号 --> 部门名
部门名 --> 部门经理
候选码:(职工编号,日期)
(2)
不是2NF。
部门名和部门经理不是完全依赖(职工编号,日期)
2NF:
R1(职工编号,日期,日营业额)
R2(职工编号,部门名,部门经理)
(3)
3NF:
R1(职工编号,日期,日营业额)
R2(职工编号,部门名,部门经理)
R2(部门名,部门经理)
4. 关系代数表达式
4.1 例题
4.1.1 知识补充
笛卡尔积、选择、投影、除、交
(1)
笛卡尔积
笛卡尔积是指两个集合之间的一种运算,其结果是一个新集合,该集合中的每个元素都是由来自第一个集合的一个元素和第二个集合的一个元素组成的有序对。如果第一个集合有m个元素,第二个集合有n个元素,那么它们的笛卡尔积将包含m×n个这样的有序对。
(2)
讲解 选择、投影、连接、除 使用的表
Student
表。主码为:学号。
Course
表。主码为:课程号。
SC
表。主码为:(学号,课程号)。
(3)
选择
(4)
投影
(5)
连接
连接一般有两步:
(1)先做笛卡尔积
(2)再根据连接条件进行筛选
外连接(也称为全外连接)是返回两个关系中所有元组的连接,无论它们是否匹配。如果某个关系中没有匹配的元组,则在结果中补充NULL值。
左连接是返回左关系中所有元组的连接,以及右关系中与左关系元组匹配的元组。如果左关系中的元组在右关系中没有匹配的元组,则结果中相应的位置将填充为NULL值。
右连接是返回右关系中所有元组的连接,以及左关系中与右关系元组匹配的元组。如果右关系中的元组在左关系中没有匹配的元组,则结果中相应的位置将填充为NULL值。
(6)
除运算
(7)
交:交集操作是指找出两个集合中共有的元素。在数据库中,这通常意味着找出同时满足两个或多个表中条件的记录。例如,如果有两个表A和B,交集操作可以找出同时存在于A和B中的记录。
4.1.2 题
设学生选课数据库中有三个关系:
学生(学号,姓名,性别,年龄,系别,专业)
课程(课号,课名,学分)
选课(学号,课号,成绩)
其中下划线标识了每个关系的关键字,要求用关系代数表达式表达每个查询语句。
(1)查询选修了“数据库”课程的学生姓名。
(2)查询没有选修C3号课程的学生姓名。
(3)查询选修了课程号为C123或C256的学生的学号和成绩
(4)查询既选修了C1号课程又选修了C2号课程的学生姓名和系别。
(5)查询选修了全部课程的学生的姓名。
4.1.3 解题
(1)查询选修了 “数据库” 课程的学生姓名。
分析思路:
首先需要通过课程关系找到 “数据库” 课程对应的课号,然后依据选课关系找到选修了该课号课程的学号,最后利用学生关系获取这些学号对应的学生姓名。
关系代数表达式:
(2)查询没有选修 C3 号课程的学生姓名。
分析思路:
先找出选修了 C3 号课程的学生学号集合,然后用全体学生的学号集合减去选修了 C3 号课程的学号集合,得到未选修 C3 号课程的学生学号集合,最后通过学生关系获取这些学号对应的学生姓名。
关系代数表达式:
(3)查询选修了课程号为 C123 或 C256 的学生的学号和成绩。
分析思路:
分别找出选修了 C123 课程和选修了 C256 课程的学生选课记录,然后将这两部分记录进行并集操作,最后投影出学号和成绩这两个属性。
关系代数表达式:
(4)查询既选修了 C1 号课程又选修了 C2 号课程的学生姓名和系别。
分析思路:
先分别找出选修了 C1 号课程的学生学号集合和选修了 C2 号课程的学生学号集合,然后通过交集操作得到同时选修了这两门课程的学生学号集合,最后利用学生关系获取这些学号对应的学生姓名和系别。
关系代数表达式:
(5)查询选修了全部课程的学生的姓名。
分析思路:
先计算课程关系中的所有课程数量(设为集合C),对于每个学生,找到其选修的课程集合(设为集合S),然后判断C是否是S的子集,如果是,则该学生选修了全部课程,最后获取这些学生的姓名。这个过程可以利用除法运算来实现,先构造一个临时关系,包含所有课程的课号,再用选课关系除以这个临时关系,得到选修了全部课程的学生学号集合,最后通过学生关系获取姓名。
关系代数表达式: