Not just for exam.
参考:林子雨老师的《数据库系统原理》,以及《软件设计师教程》
写在前面:刻在DNA里的学生选课数据库
本章的所有实例都以学生选课数据库为基础,该数据库包括5个表:
学生表Student(Sno, Sname, Ssex, Sage, Sdept);
课程表Course(Cno, Cname, Cpno, Ccredit);
学生选课表SC(Sno, Cno, Grade);
教师表Teacher(Tno, Tname, Tsex, Tage);
授课表TC(Tno, Cno)。
每一个表的第一列都是主码。
Student
Sno
Sname
Sex
Sage
Sdept
2024001
林书凡
男
18
MA
2024002
李欣然
女
19
IS
2024003
王武义
男
20
CS
2024004
苏文甜
女
19
CS
Course
Cno
Cname
Cpno
Ccredit
1
大数据
3
2
2
操作系统
5
4
3
数据库
5
4
4
编译原理
NULL
4
5
编程语言
NULL
2
6
数据挖掘
3
2
SC
Sno
Cno
Grade
2024001
1
97
2024001
2
78
2024001
3
86
2024002
2
85
2024002
3
77
Teacher
Tno
Tname
Tsex
Tage
97001
林形文
男
45
97002
司马鹰松
男
33
97003
王明天
男
38
97004
马晓燕
女
36
97005
张勇
男
51
TC
Tno
Cno
97001
1
97001
3
97002
2
97003
4
97004
5
97004
6
97005
6
数据库概述 关系数据库 关系运算 逻辑表达式
运算符
含义
比较运算符
>
大于
>=
大于等于
<
小于
<=
小于等于
=
等于
<>
不等于
逻辑运算符
¬
非
∧
与
∨
或
八种关系运算
并(Union) :
符号:
作用:合并两个关系中的元组,去除重复的元组。
表示: ,表示关系R和关系S的并集。
交(Intersection) :
符号:
作用:找出两个关系中共有的元组。
表示: ,表示关系R和关系S的交集。
差(Difference) :
符号:
作用:从第一个关系中移除与第二个关系中相同的元组。
表示: ,表示关系R中不在关系S中的元组。
选择(Selection) :
符号:
作用:从关系中选择满足特定条件的元组(行 )。
表示:条 件 ,表示从关系R中选择满足条件的元组。
投影(Projection) :
符号:
作用:从关系中选择特定的属性列 。
表示:属 性 列 表 ,表示从关系R中选择指定的属性列。
连接(Join) :
符号:
作用:将两个关系中满足特定条件的元组合并成一个新的关系。
表示: ,表示关系R和关系S的自然连接。
条件连接 (θ-连接 ): ,其中 是连接条件, 可以是 、 、 等比较运算符,表示基于这些条件的连接。
外连接 (Outer Join):当两个关系中没有完全匹配的元组时,外连接可以返回其中一个关系的所有元组,以及另一个关系中匹配的元组。如果另一个关系中没有匹配的元组,则结果中对应的字段为NULL。
左外连接 (Left Outer Join):返回左关系(R)的所有元组,即使在右关系(S)中没有匹配的元组。如果右关系中没有匹配的元组,则结果中右关系的部分为NULL。
表示:Double subscripts: use braces to clarify R \underset{A \theta B}{\Join}_{\text{L}} S 或者 ⟕
右外连接 (Right Outer Join):返回右关系(S)的所有元组,即使在左关系(R)中没有匹配的元组。如果左关系中没有匹配的元组,则结果中左关系的部分为NULL。
表示:Double subscripts: use braces to clarify R \underset{A \theta B}{\Join}_{\text{R}} S 或者 ⟖
全外连接 (Full Outer Join):返回两个关系中任一关系的所有元组,无论另一个关系中是否有匹配的元组。如果另一个关系中没有匹配的元组,则结果中对应的字段为NULL。
表示:Double subscripts: use braces to clarify R \underset{A \theta B}{\Join}_{\text{FULL}} S 或者 ⟗
笛卡尔积(Cartesian Product) :
符号:×
作用:将两个关系中的每个元组与另一个关系中的每个元组配对,形成所有可能的组合。
表示:R × S,表示关系R和关系S的笛卡尔积。
除(Division) :
符号:÷
作用:找出能够与第二个关系中所有元组配对的第一个关系中的元组。
表示:R ÷ S,表示关系R中能够与关系S中所有元组配对的元组。
简单理解:
选择是取行,投影是取列。
自然连接中,如果两个表有相同的列名,那两个表相同列名的列,具体值也要相同,才能配对。所以左右表都有可能会删去一些不匹配的行。
左外连接中,左边表的所有行都会被保留,即使右边表中没有匹配的行,此时右边表对应的位置会用NULL填充。
右外连接同理。
全外连接中,左右两边表的所有行都会被保留,无论是不是匹配,当有一边没有匹配时,那一边对应的位置会用NULL填充。
笛卡尔积就是两个表直接不由分说地连,行 列 大小的表A和 行 列 大小的的表B,笛卡尔积得到行 列 的表C,与连接不同。
除如图:
关系运算的sql表示
并(Union)
1 2 3 SELECT column_name(s) FROM table1UNION SELECT column_name(s) FROM table2;
交(Intersection)
1 2 3 SELECT column_name(s) FROM table1INTERSECT SELECT column_name(s) FROM table2;
差(Difference)
1 2 3 SELECT column_name(s) FROM table1EXCEPT SELECT column_name(s) FROM table2;
选择(Selection)
1 2 SELECT * FROM table WHERE condition ;
投影(Projection)
1 SELECT column_names FROM table ;
连接(Join)
自然连接(Natural Join)
1 2 SELECT * FROM table1NATURAL JOIN table2;
条件连接(θ-连接)
1 2 SELECT * FROM table1JOIN table2 ON condition ;
外连接(Outer Join)
左外连接(Left Outer Join)
1 2 SELECT * FROM table1LEFT JOIN table2 ON condition ;
右外连接(Right Outer Join)
1 2 SELECT * FROM table1RIGHT JOIN table2 ON condition ;
全外连接(Full Outer Join)
1 2 SELECT * FROM table1FULL JOIN table2 ON condition ;
笛卡尔积(Cartesian Product)
1 SELECT * FROM table1, table2;
除(Division)
1 2 3 4 5 SELECT column_names FROM table1WHERE NOT EXISTS ( SELECT * FROM table2 WHERE table1.column = table2.column );
习题 学生数据库 已知数据库
学生表S(Sno, Sname, Ssex, Sage, Sdept);
课程表C(Cno, Cname, Cpno, Ccredit);
学生选课表SC(Sno, Cno, Grade);
完成:
检索选修课程名为“数学”的学生的学号和姓名。
检索至少选修了课程号为 1 和 3 的学生的学号。
检索选修了“操作系统”或“数据库”课程的学生的学号和姓名。
检索年龄在 18~20 之间(含 18 和 20)的女生的学号、姓名及年龄。
检索选修了“数据库”课程的学生的学号、姓名及成绩。
检索选修了全部课程的学生的姓名所在系。
检索选修课程包括 1042 学生所学课程的学生的学号。
检索不选修 2 课程的学生的姓名和所在系。
My answer:打latex也太难了吧,我直接开始歪歪地手写
关系数据库标准语言SQL 视图在数据字典中保存的是视图定义
关系数据库编程 关系数据库安全和保护 关系数据库的规范化理论 关系模式中可能存在的冗余和异常问题
数据冗余
不一致性
插入异常
删除异常函数依赖 定义
函数依赖 :设 为任一给定关系,如果对于 中属性 的每一个值, 中的属性 只有唯一值与之对应,则称 函数决定 ,或 函数依赖 于 X,记作 。其中,X 称为决定因素 。反之,对于关系 中的属性 和 ,若 不能函数决定 Y,则其符号记作 。
平凡的函数依赖 :设 是一个函数依赖,若 ,则称 是一个平凡的函数依赖 。
完全函数依赖 :设 是一个函数依赖,并且对于任何 , 都不成立,则称 是一个完全函数依赖 ,记作 。
部分函数依赖 :设 是一个函数依赖,但不是完全函数依赖,则称 是一个部分函数依赖 ,记作 。
传递函数依赖 :设 是一个关系模式, , , ,如果 , ,且 , , ,则称 传递函数依赖 于 , 。
候选码 :设 为任一给定关系模式, 为其所含的全部属性集合, 为 的子集,若有完全函数依赖 ,则 为 的一个候选码 。
主属性和非主属性 :包含在任何一个候选码中的属性为主属性,否则为非主属性。
理解
普通函数依赖(X→Y) 想象你的身份证号码(X)就像一把万能钥匙,它能直接确定你的姓名(Y)、性别、出生地。只要知道身份证号,其他信息都能唯一确定。例如:学号→姓名,就像每个学号对应唯一的学生。
平凡依赖 vs 非平凡依赖
平凡就像「已知父亲名字,自然知道家族姓氏」(因为姓氏已经是父亲名字的一部分)
非平凡像「快递单号与包裹信息」,单号能唯一确定收件人的电话(例如单号 SF123456 对应电话 13800001111),但电话不是单号的子集,这也是非平凡函数依赖
完全依赖 vs 部分依赖 完全依赖就像「用完整钥匙开锁」:
成绩完全依赖(学号+课程号)组合,单独学号或课程号都不够
部分依赖像「用半截钥匙就能开锁」:
如果课程名称只依赖课程号(而课程号是主键的一部分),就是部分依赖
传递依赖(连锁反应) 学号→系号→系主任,系主任像被「间接遥控」确定。这会导致数据冗余(多个学生重复存储系主任信息)
候选码就像「能开所有锁的最小钥匙组合」:
比如(学号+课程号)组合才能确定成绩,单独一个都不行
主属性是所有候选码中的零件:
如果候选码是学号,那么学号就是主属性;如果候选码是(学号+身份证号),两者都是主属性
范式
第一范式(1NF) 如果关系模式 的每一个 属性对应的域值都是不可再分的,称模式 属于第一范式,记作 。若数据库模式 中的每个关系模式都是 ,则数据库模式 。
最基本的要求,就是表中的每个属性都不可再分。例如,学生信息表中,每个学生的姓名、年龄、性别等都是不可再分的。
第二范式(2NF) 如果关系模式 ,并且每个非主属性都完全函数依赖于 的码,则 。
不能有部分依赖。例如,在选课表中,学生成绩应该依赖于学号和课程号的组合,而不是单独依赖学号或课程号。
第三范式(3NF) 关系模式 R 中若不存在这样的码 、属性组 及非主属性 ,使得 、 和 成立,则称 。
例如,学生表中的成绩不能依赖于学生的姓名,因为姓名不是码。
Boyce-Codd范式(BCNF) 若 ,而且R中没有任何属性传递函数依赖于R中的码,则关系模式 。
第四范式(4NF) 了解一下就可以了。
第五范式(5NF) 了解一下就可以了。
理解
1NF(基础版) 要求:每个字段都是最小单元,不能拆。错误示范 :把「联系电话」写成 “13800001111,13800002222”(应拆分成多行)
2NF(消灭半吊子依赖) 必须消灭部分依赖。比如选课表中:
3NF(斩断连锁依赖) 禁止传递依赖。比如学生表里直接存系主任名字:
错误:学生表包含系号→系主任
正确:拆分成「学生表(学号+系号)」和「院系表(系号+系主任)」
BCNF(加强版3NF) 连主属性都不能有传递依赖。举个极端例子:
假设每个老师只教一门课,每门课有多个老师
错误表:(老师ID,课程)主键是老师ID,但课程→教室(课程不是主键)
正确:拆分成「老师-课程表」和「课程-教室表」
举个综合例子(学生选课系统): 原始混乱表 | 学号 | 姓名 | 课程号 | 课程名 | 成绩 | 系名 | 系主任 | |—-|—-|—-|—-|—-|—-|—-| | 001 | 张三 | C01 | 数学 | 90 | 计算机系 | 李主任 |
问题分析:
课程名只依赖课程号(违反2NF)
系主任依赖系名,系名依赖学号(传递依赖,违反3NF)
助记小漫画(但是记的可能不是数据库知识点) </details>
规范化后:
学生表(学号,姓名,系名)3NF
课程表(课程号,课程名)2NF
选课表(学号,课程号,成绩)2NF
院系表(系名,系主任)3NF
这样修改后,更新系主任信息只需要修改院系表中的一个位置,避免了数据冗余和更新异常。
模式分解 习题 2021上半年软考 42题 给定关系R(U,F),其中U={A,B,C,D,E,H},F={(A→B,B→DH,A→H,C→E)}。关系有( ),F中( )。
问题1:
[ ] A. 1个候选码A
[ ] B. 2个候选码A、B
[x] C. 1个候选码AC
[ ] D. 2个候选码A、C
问题2:
[ ] A. 不存在传递依赖,但存在冗余函数依赖
[ ] B. 既不存在传递依赖,也不存在冗余函数依赖
[ ] C. 存在传递依赖A→D和A→H,但不存在冗余函数依赖
[x] D. 存在传递依赖A→D和A→H,并且还存在冗余函数依赖