第2章 关系数据库
第2章 关系数据库
2.1 本章总览
本章围绕关系模型展开,核心任务是回答四个问题:
- 关系数据库中的数据长什么样:用二维表表示数据,即“关系”。
- 关系数据库中的数据如何操作:查询、插入、删除、修改。
- 关系数据库中的数据要满足什么约束:实体完整性、参照完整性、用户定义完整性。
- 关系查询如何形式化表达:用关系代数描述查询过程。
从学习路径上看,本章可以概括为:
- 先掌握关系模型的数据结构;
- 再理解关系操作与关系语言;
- 接着掌握完整性约束;
- 最后学习关系代数,为后续 SQL 学习打基础。
2.2 关系模型的数据结构及形式化定义
2.2.1 关系模型的核心特征
关系模型有三个非常重要的特点:
-
单一的数据结构——关系
- 现实世界中的实体以及实体之间的联系,都用关系表示。
- 从用户视角看,关系就是一张二维表。
-
建立在集合论基础上
- 关系中的数据本质上是集合中的元素。
- 因此,关系中的行、列顺序通常都不是本质属性。
-
以集合操作为主要操作方式
- 查询和更新都以“集合”为单位进行,而不是逐条记录处理。
2.2.2 域(Domain)
域是一个属性可能取值的集合,并且这些值具有相同的数据类型。
定义
域是一组具有相同数据类型的值的集合。
例子
- 整数集合
- 实数集合
- 0~100 的正整数
- 指定长度的字符串集合
{男, 女}
理解要点
域可以理解为“某类属性允许取什么值”的范围。
例如:
性别的域可以是{男, 女}学分的域可以是{1, 2, 3, 4}出生日期的域可以是所有合法日期
也就是说,属性的取值不是随便写的,而是来自某个域。
2.2.3 笛卡尔积(Cartesian Product)
定义
给定一组域 D1, D2, …, Dn,其笛卡尔积定义为:
D1 × D2 × … × Dn = {(d1, d2, …, dn) | di ∈ Di, i = 1, 2, …, n}
含义
笛卡尔积表示:从每个域中各取一个值,形成的所有可能组合的集合。
相关术语
- 元组(Tuple):笛卡尔积中的每一个元素
- 分量(Component):元组中的每一个位置上的值
- 基数:集合中元素的个数
例子
设:
D1 = {张清玫, 刘逸}D2 = {计算机科学与技术, 信息管理与信息系统}D3 = {李勇, 刘晨, 王敏}
则:
D1 × D2 × D3的基数为2 × 2 × 3 = 12
例如元组:
(张清玫, 计算机科学与技术, 刘晨)
其中:
张清玫、计算机科学与技术、刘晨分别是三个分量。
理解要点
笛卡尔积只是“所有可能组合”,通常并不都具有现实意义。
例如“导师—专业—研究生”的全部组合,并不意味着这些组合都真实存在。
2.2.4 关系(Relation)
定义
在关系模型中,D1 × D2 × … × Dn 的一个有意义的子集称为在域 D1, D2, …, Dn 上的一个关系,记作:
R(D1, D2, …, Dn)
它是一个 n 目关系,其中 n 称为关系的目或度。
关系的本质
关系不是全部可能组合,而是有实际语义的组合集合。
关系中的基本概念
-
关系
- 笛卡尔积的一个有意义的子集。
-
元组
- 关系中的每个元素称为元组,通常记为
t。
- 关系中的每个元素称为元组,通常记为
-
属性
- 关系中每一列称为一个属性。
-
关系的表示
- 关系通常用二维表表示。
- 表中的每一行对应一个元组。
- 表中的每一列对应一个属性。
三类关系
-
基本关系(基本表、基表)
- 实际存储在数据库中的表。
-
查询结果
- 查询执行后临时产生的结果表。
-
视图表
- 由基本表或其他视图导出的虚表。
- 视图本身通常不存储实际数据。
2.2.5 基本关系的性质
基本关系必须满足以下性质:
-
列是同质的
- 同一列中的值必须来自同一个域。
- 也就是说,同一属性的数据类型和语义应一致。
-
不同列可以来自同一个域
- 例如“学号”和“班长学号”都可以来自学号域。
- 但属性名必须不同,以区分含义。
-
列的顺序无关
- 列交换顺序后,关系本质不变。
-
任意两个元组不能完全相同
- 关系中不允许出现重复元组。
-
行的顺序无关
- 行交换顺序后,关系本质不变。
-
分量必须是原子值
- 每个属性值都必须不可再分。
- 这是规范化关系最基本的要求。
理解要点
关系本质上是一个集合,而不是 Excel 那种“看起来像表”的普通表格。
因此:
- 集合中元素无序,所以行无序;
- 属性位置无本质区别,所以列无序;
- 集合中不允许重复元素,所以元组不能重复;
- 原子性要求一个单元格里不能再嵌套一个表或列表。
补充
满足这些规范条件的关系称为规范化关系,简称属于某种范式(Normal Form, NF)。范式的详细内容通常在后续章节学习。
2.3 关系模式
2.3.1 什么是关系模式
关系模式是对关系的结构性描述,它回答的是:
- 这个关系有哪些属性;
- 每个属性来自什么域;
- 属性之间有什么约束;
- 这些属性如何组织成一个关系。
关系模式描述的内容
-
元组集合的结构
- 属性由哪些字段构成
- 属性来自哪些域
- 属性和域之间的映射关系
-
完整性约束条件
- 比如主码不能为空
- 外码必须引用已存在的主码值
关键理解
- 关系模式是“型”
- 关系是“值”
可以类比为:
- 类定义 vs 对象实例
- 表结构 vs 表中的数据
2.3.2 关系模式与关系的区别
关系模式
- 是对关系的描述;
- 是静态的、相对稳定的;
- 对应“表结构”。
关系
- 是关系模式在某一时刻的状态或内容;
- 是动态的,会随插入、删除、修改而变化;
- 对应“表中的数据”。
举例
例如课程表的建表语句:
create table course(
cno char(5) primary key,
cname char(40) not null,
ccredit int check(ccredit > 0),
cpno char(5)
)
这描述的是关系模式。
而执行:
insert into course values
('81001', '程序设计基础与C语言', 4, null),
('81002', '数据结构', 4, '81001')
插入后的具体数据,属于该模式对应的关系。
一句话总结
- 模式管“长什么样”
- 关系管“当前存了什么”
2.3.3 关系模式的形式化定义
关系模式可以形式化表示为:
R(U, D, DOM, F)
其中:
R:关系名U:属性名集合D:属性所属域的集合DOM:属性到域的映射集合F:属性间数据依赖关系的集合
在实际使用中,关系模式常简记为:
R(U) 或 R(A1, A2, …, An)
其中:
R是关系名A1, A2, …, An是属性名
例子
Student(Sno, Sname, Ssex, Sbirthdate, Smajor)
Course(Cno, Cname, Ccredit, Cpno)
SC(Sno, Cno, Grade, Semester, TeachingClass)
这里:
Student表示学生关系模式;Course表示课程关系模式;SC表示学生选课关系模式。
2.4 关系中的码
码是关系模型中极其重要的概念,它决定了“如何唯一标识一个元组”。
2.4.1 候选码(Candidate Key)
定义
若关系模式中的某一个属性或属性组的值能够唯一标识一个元组,并且它的任何真子集都不能唯一标识元组,则该属性或属性组称为候选码。
理解要点
候选码必须满足两个条件:
-
唯一性
- 能唯一确定一条记录。
-
最小性
- 去掉其中任何一个属性后,就不能保证唯一。
例子
在学生表中:
学号能唯一标识一个学生;- 且再去掉就没了,因此
学号是候选码。
如果某个关系中要靠 (学号, 课程号) 组合才能唯一标识一条记录,那么这个属性组就是候选码。
2.4.2 主码(Primary Key)
若一个关系有多个候选码,则从中选定一个作为主码。
理解要点
- 候选码可能有多个;
- 主码只能选一个;
- 主码是数据库设计时“主要采用的唯一标识方式”。
2.4.3 主属性与非主属性
- 主属性:包含在任一候选码中的属性
- 非主属性:不包含在任何候选码中的属性
例子
若 (学号, 课程号) 是某关系的候选码,则:
学号、课程号是主属性;成绩、学期、教学班等若不在任何候选码中,就是非主属性。
2.4.4 全码(All-Key)
若关系模式的全部属性组合才构成这个关系模式的候选码,则称为全码。
例子
关系 (教师, 课程, 学生) 中,若限定:
- 一个教师可以讲授多门课程;
- 一门课程可以由多个教师讲授;
- 一个学生可以选不同教师讲授的不同课程;
则仅靠:
- 教师 不能唯一确定;
- 课程 不能唯一确定;
- 学生 不能唯一确定;
- 教师+课程 也不一定唯一;
- 教师+学生 也不一定唯一;
- 课程+学生 也不一定唯一;
必须 (教师, 课程, 学生) 三者合起来才唯一,此时该关系的候选码就是全码。
2.5 关系数据库
2.5.1 什么是关系数据库系统
关系数据库系统是支持关系模型的数据库系统。
它的基本思想是:
- 实体用关系表示;
- 实体之间的联系也用关系表示。
例子
学生选课数据库中:
- 学生实体可以表示为
Student - 课程实体可以表示为
Course - 学生选课这一多对多联系可以表示为
SC
2.5.2 什么是关系数据库
在一个关系数据库中,某一时刻所有关系模式对应的关系的集合,构成一个关系数据库。
解释
“关系数据库”不是单独某一张表,而是:
- 多个相互联系的关系模式
- 在某一时刻对应的一组具体关系
共同组成的整体。
也就是说:
Student当前有哪些元组;Course当前有哪些元组;SC当前有哪些元组;
它们一起构成了此刻的关系数据库状态。
2.5.3 关系模型的存储结构
关系模型是逻辑结构层面的概念,而物理上如何存储,不同 DBMS 可以不同。
两种常见思路
-
一个表对应一个操作系统文件
- 由操作系统完成底层文件组织。
-
数据库系统自行管理大文件空间
- 数据库系统先向操作系统申请大文件;
- 再自行划分存储空间;
- 组织表、索引等存储结构;
- 完成自己的存储管理。
理解要点
- 关系模型强调的是逻辑结构;
- 物理实现可以千差万别;
- 用户日常操作主要面对的是逻辑层,而不是物理存储细节。
2.6 关系操作
2.6.1 常用关系操作
关系操作分为两大类:
1. 查询操作
包括:
- 选择
- 投影
- 连接
- 除
- 并
- 差
- 交
- 笛卡尔积
其中通常把以下五种看作基本操作:
- 选择
- 投影
- 并
- 差
- 笛卡尔积
2. 数据更新操作
包括:
- 插入
- 删除
- 修改
2.6.2 关系操作的特点
1. 集合操作方式
关系操作的对象和结果都是集合,因此通常是“一次处理一个集合”。
2. 封闭性
关系操作的输入和输出都是关系。
这意味着:
- 操作对象是关系;
- 中间结果还是关系;
- 最终结果仍然是关系。
理解要点
正因为“结果仍然是关系”,所以关系操作可以层层嵌套、连续组合。
这也是 SQL 能写复杂查询的基础。
2.6.3 关系数据库语言的分类
关系数据库语言大体可以分为三类:
1. 关系代数语言
代表:ISBL
特点:
- 以运算为中心;
- 通过一系列关系运算构造查询。
2. 关系演算语言
分为:
- 元组关系演算
- 代表:
ALPHA、QUEL
- 代表:
- 域关系演算
- 代表:
QBE
- 代表:
特点:
- 以逻辑描述为中心;
- 描述“满足什么条件的数据要被找出来”。
3. 结构化查询语言 SQL
SQL 同时具有:
- 关系代数的运算思想
- 关系演算的描述思想
因此它是最常用、最实用的关系数据库语言。
2.7 关系的完整性
完整性约束用于保证数据正确、有效、一致。
关系模型中主要有三类完整性约束:
- 实体完整性
- 参照完整性
- 用户定义的完整性
其中:
- 实体完整性和参照完整性是关系模型必须满足的基本约束;
- 用户定义完整性是具体业务语义提出的约束。
2.7.1 实体完整性
规则
若属性 A 是基本关系 R 的主属性,则属性 A 不能取空值。
这条规则称为实体完整性规则(Entity Integrity)。
为什么主码不能空
主码的作用是唯一标识元组。
如果主码为空,那么:
- 无法区分这条记录是谁;
- 无法唯一标识实体;
- 也无法作为其他关系引用的目标。
例子
关系:
选修(学号, 课程号, 成绩)
若 (学号, 课程号) 是主码,那么:
学号不能空;课程号不能空。
空值的含义
空值不等于 0,也不等于空字符串。
空值一般表示:
- 不知道
- 不存在
- 无意义
一句话理解
主码不能为空,是为了保证每个元组都能被明确识别。
2.7.2 参照完整性
参照完整性描述的是关系之间引用的一致性。
外码(Foreign Key)的定义
设 F 是基本关系 R 的一个或一组属性,但 F 不是关系 R 的码。
如果 F 与基本关系 S 的主码 Ks 相对应,则称 F 是 R 的外码。
其中:
R称为参照关系(Referencing Relation)S称为被参照关系(Referenced Relation)
说明
-
R和S不一定是不同的关系。- 也就是说,一个关系可以引用自己。
- 例如课程表中的“先修课”引用课程表自身的主码“课程号”。
-
外码与被参照主码必须定义在同一个域上,或在一组对应域上。
-
外码和主码未必同名,但在设计中通常会尽量同名,便于理解。
参照完整性规则
若属性(组)F 是关系 R 的外码,它与关系 S 的主码 Ks 相对应,则对于 R 中每个元组,F 上的值必须满足:
-
要么取空值
- 且若是属性组,则组内每个属性都应为空;
-
要么等于
S中某个元组的主码值
直观解释
外码的值只能来自两个来源:
- 空
- 被参照表中已经存在的主码值
不能凭空写一个数据库中根本不存在的值。
例子 1:学生与专业
关系:
- 学生(学号,姓名,性别,出生日期,主修专业)
- 专业(专业名,专业编号)
若 学生.主修专业 引用 专业.专业名,则:
- 可以为空,表示尚未分配专业;
- 若不为空,则必须等于专业表中某个已存在的“专业名”。
不能出现一个根本不存在的专业。
例子 2:学生、课程与选课
关系:
- 学生(学号,姓名,性别,出生日期,主修专业)
- 课程(课程号,课程名,学分,先修课)
- 学生选课(学号,课程号,成绩,选课学期,教学班)
此时:
学生选课.学号是外码,引用学生.学号学生选课.课程号是外码,引用课程.课程号
由于 学号 和 课程号 在选课关系中通常又属于主码,因此它们:
- 作为主属性,不能取空值;
- 作为外码,又必须引用已存在的学生和课程。
这说明一个属性可以同时受到实体完整性和参照完整性的约束。
例子 3:课程的先修课
关系:
课程(课程号,课程名,学分,先修课)
其中:
先修课可以为空,表示该课程没有先修课;- 若不为空,则必须等于课程表中某个已存在的
课程号。
这是一个自引用外码的典型例子。
2.7.3 用户定义的完整性
用户定义完整性是针对某个具体应用场景所提出的约束,反映的是业务语义要求。
特点
- 与具体业务有关;
- 不是关系模型固定规定的;
- 由数据库系统提供定义和检查机制。
例子
关系:
课程(课程号,课程名,学分)
可能要求:
课程号必须唯一课程名不能为空学分只能取{1, 2, 3, 4}
这些约束不属于实体完整性或参照完整性的标准规则,但它们对业务是必要的,因此属于用户定义完整性。
常见形式
NOT NULLUNIQUECHECK- 默认值
- 触发器或更复杂业务规则
2.8 关系代数
2.8.1 什么是关系代数
关系代数是一种抽象的查询语言,它通过对关系进行运算来表达查询。
两个核心特征
- 运算对象是关系
- 运算结果仍然是关系
运算符分类
关系代数的运算符分为两类:
- 传统集合运算符
- 专门的关系运算符
其中:
- 传统集合运算主要从“行”的角度处理关系;
- 专门的关系运算既涉及“行”,也涉及“列”。
2.8.2 关系代数运算符总览
传统集合运算符
∪:并-:差∩:交×:笛卡尔积
专门的关系运算符
σ:选择π:投影⋈:连接÷:除
2.9 传统的集合运算
2.9.1 并(Union)
定义
R ∪ S 表示属于 R 或属于 S 的元组组成的关系。
形式化表示:
R ∪ S = { t | t ∈ R ∨ t ∈ S }
前提条件
并运算要求 R 和 S 并相容,即:
- 具有相同的目
n - 对应属性来自相同的域
理解
并运算就是把两个同构关系中的元组合并,并自动去重。
2.9.2 差(Difference)
定义
R - S 表示属于 R 但不属于 S 的元组组成的关系。
形式化表示:
R - S = { t | t ∈ R ∧ t ∉ S }
前提条件
同样要求 R 和 S 并相容。
理解
差运算就是“从 R 中删去那些也在 S 中出现的元组”。
2.9.3 交(Intersection)
定义
R ∩ S 表示既属于 R 又属于 S 的元组组成的关系。
形式化表示:
R ∩ S = { t | t ∈ R ∧ t ∈ S }
并且可以由差运算表示为:
R ∩ S = R - (R - S)
前提条件
仍要求 R 和 S 并相容。
2.9.4 笛卡尔积(Product)
定义
设:
R为n目关系,有k1个元组;S为m目关系,有k2个元组;
则:
R × S 是一个 (n + m) 列的关系,共有 k1 × k2 个元组。
结果的组成
- 前
n列来自R的一个元组; - 后
m列来自S的一个元组。
理解
笛卡尔积会把两个关系的每个元组两两配对。
因此结果通常会很大,并且很多组合没有实际意义。
后续常结合“选择”来筛出真正有意义的组合。
2.10 专门的关系运算前的记号
在学习选择、投影、连接、除之前,需要掌握几个记号。
2.10.1 元组与分量记号
设关系模式为:
R(A1, A2, …, An)
并设 R 是该模式的一个关系,则:
t ∈ R表示t是R的一个元组t[Ai]表示元组t在属性Ai上的分量
2.10.2 属性组记号
若:
A = {Ai1, Ai2, …, Aik}
其中 Ai1, Ai2, …, Aik 是 A1, A2, …, An 的一部分,则 A 称为属性列或属性组。
此时:
t[A] = (t[Ai1], t[Ai2], …, t[Aik])
表示元组 t 在属性组 A 上的分量集合。
Ā 表示从 {A1, A2, …, An} 中去掉属性组 A 后剩余的属性组。
2.10.3 元组的连接
若:
tr ∈ Rts ∈ S
则 tr ts 称为元组的连接,表示把两个元组拼接成一个新元组。
如果:
R是n元组S是m元组
则 tr ts 是一个 n + m 列的元组:
- 前
n个分量来自R - 后
m个分量来自S
2.10.4 象集(Image Set)
给定关系:
R(X, Z)
其中 X 和 Z 为属性组。
当 t[X] = x 时,x 在 R 中的象集定义为:
Zx = { t[Z] | t ∈ R, t[X] = x }
含义
它表示:
在关系 R 中,属性组 X 上取值为 x 的那些元组,在属性组 Z 上的取值集合。
例子
若关系 R(X, Z) 中有:
x1对应Z1, Z2, Z3x2对应Z2, Z3x3对应Z1, Z3
则:
Zx1 = {Z1, Z2, Z3}Zx2 = {Z2, Z3}Zx3 = {Z1, Z3}
理解要点
象集是理解除运算的关键。
因为除运算本质上就是判断“某个 x 对应的象集,是否包含了指定集合”。
2.11 专门的关系运算
2.11.1 选择(Selection)
定义
在关系 R 中,选择满足给定条件的元组,记作:
σF(R) = { t | t ∈ R ∧ F(t) = 真 }
其中:
F是选择条件;- 常见基本形式是
X θ Y; θ可以是>、≥、<、≤、=、≠。
作用
选择是从关系中“按条件筛行”。
直观理解
- 选择处理行
- 保留满足条件的元组
- 可以理解成 SQL 中的
WHERE
例子 1
查询信息安全专业全体学生:
σSmajor='信息安全'(Student)
例子 2
查询 2001 年之后(包括 2001 年)出生的学生:
σSbirthdate >= '2001-01-01'(Student)
易懂总结
选择就是:
从整张表中挑出满足条件的记录。
2.11.2 投影(Projection)
定义
从关系 R 中取出若干属性列,组成新的关系,记作:
πA(R) = { t[A] | t ∈ R }
其中 A 是 R 中的属性列或属性组。
作用
投影是“按列取数据”。
直观理解
- 投影处理列
- 只保留想要的属性
- 可理解成 SQL 中的
SELECT 某些列
例子 1
查询学生的姓名和主修专业:
πSname, Smajor(Student)
例子 2
查询学生关系中都有哪些专业:
πSmajor(Student)
关键点:投影会去重
因为关系是集合,所以投影后的重复元组会被自动消除。
例如多个学生都来自“计算机科学与技术”,投影 Smajor 后只保留一个“计算机科学与技术”。
一句话理解
投影就是:
从表中抽取指定列,并自动去重。
2.11.3 连接(Join)
连接用于把两个关系中有关联的元组组合起来。
常见两类连接
- 等值连接
- 自然连接
1. 等值连接
等值连接是先做笛卡尔积,再选出两个关系中某些属性值相等的元组。
例如:
R ⋈_{R.B = S.B} S
其思想相当于:
- 先做
R × S - 再保留满足
R.B = S.B的元组
特点
- 相等条件两边的属性通常都会保留;
- 因此结果中可能同时出现
R.B和S.B两列。
2. 自然连接
自然连接是在等值连接基础上的进一步简化:
- 自动以两个关系中的同名属性相等为连接条件;
- 并在结果中去掉重复的公共属性列。
记作:
R ⋈ S
特点
- 更简洁
- 结果更自然
- 常用于关系模式中具有公共属性的情况
悬浮元组(Dangling Tuple)
在自然连接时,若关系 R 中某些元组在 S 中找不到公共属性值相等的对应元组,那么这些元组会被舍弃。被舍弃的元组称为悬浮元组。
直观理解
自然连接默认只保留“能对上号”的元组。
对不上号的就丢掉,这些被丢掉的就是悬浮元组。
外连接(Outer Join)
如果希望把悬浮元组也保留下来,并把匹配不到的属性填空值 NULL,这种连接称为外连接。
包括:
-
左外连接
- 保留左关系的全部元组;
- 右边匹配不到的补
NULL。
-
右外连接
- 保留右关系的全部元组;
- 左边匹配不到的补
NULL。
-
全外连接
- 两边所有元组都保留;
- 哪边匹配不到,哪边补
NULL。
理解要点
- 自然连接:只保留成功匹配的
- 外连接:把没匹配上的也保留
2.11.4 除运算(Division)
除运算是关系代数中最难理解、但非常重要的运算之一。
基本形式
给定:
R(X, Y)S(Y, Z)
其中 X、Y、Z 为属性组。
R 中的 Y 与 S 中的 Y 可以名字不同,但必须来自相同的域集。
则 R ÷ S 的结果是一个新的关系 P(X)。
形式化定义
P 是 R 中满足下列条件的元组在 X 属性列上的投影:
R ÷ S = { tr[X] | tr ∈ R ∧ πY(S) ⊆ Yx }
其中:
x = tr[X]Yx是x在R中的象集
直观含义
除运算的核心意思是:
找出那些在 R 中与 S 指定的全部 Y 值都发生过对应关系的 X 值。
换句话说:
除运算通常对应查询“全部”“都”“至少包含某集合中的所有元素”这一类问题。
更通俗地理解
如果把 R(X, Y) 看成“X 和 Y 之间存在关系”,
把 S(Y) 看成“一组要求的 Y”,
那么 R ÷ S 就是在找:
哪些 X 与 S 中全部这些 Y 都有关联。
例子理解
若:
R(A, B, C)中,某个A = a1对应的(B, C)象集为{(b1,c2), (b2,c1), (b2,c3)}S(B, C, D)在(B, C)上的投影为{(b1,c2), (b2,c1), (b2,c3)}
那么 a1 满足要求,因此出现在 R ÷ S 的结果中。
若某个 A 的象集缺少其中任意一个组合,就不能出现在结果中。
结果只有 X 列
这一点特别重要:
R(X, Y) ÷ S(Y, Z)的结果只保留X部分- 结果不是完整元组,而是满足“包含全部要求”的那些
X值
2.12 关系代数综合例子
下面结合学生选课数据库来理解关系代数。
设有关系:
Student(Sno, Sname, Ssex, Sbirthdate, Smajor)Course(Cno, Cname, Ccredit, Cpno)SC(Sno, Cno, Grade, Semester, TeachingClass)
2.12.1 查询选修了 81002 号课程的学生学号
关系代数表达式:
πSno(σCno='81002'(SC))
解释
- 先从
SC中选出课程号为81002的元组; - 再投影出学号列。
2.12.2 查询没有选修 81002 号课程的学生学号
关系代数表达式:
πSno(Student) - πSno(σCno='81002'(SC))
解释
πSno(Student)得到所有学生学号;πSno(σCno='81002'(SC))得到选了 81002 的学生学号;- 两者相减,得到没选该课的学生学号。
易错点
不能写成:
πSno(SC) - πSno(σCno='81002'(SC))
因为 πSno(SC) 只包含“至少选过一门课的学生”,会漏掉从未选课的学生。
题目问的是“所有学生中没有选修 81002 的人”,因此左边必须从 Student 出发。
2.12.3 查询至少选修了 81001 号课程和 81003 号课程的学生号码
思路
先建立一个临时关系:
K(Cno) = {81001, 81003}
再计算:
πSno, Cno(SC) ÷ K
含义
找出那些学号 Sno,使得它对应的课程集合至少包含 81001 和 81003。
结果语义
结果是“同时选过 81001 和 81003 的所有学生学号”。
2.12.4 查询选修了全部课程的学生号码和姓名
关系代数表达式可写为:
πSno, Cno(SC) ÷ πCno(Course) ⋈ πSno, Sname(Student)
思路拆解
πCno(Course):取出所有课程号,作为“全部课程集合”;πSno, Cno(SC) ÷ πCno(Course):找出选修了全部课程的学生学号;- 再与
πSno, Sname(Student)连接,得到姓名。
本质
这是“全部”类查询,最典型地适合用除运算表示。
2.12.5 查询至少选修了一门其直接先行课为 81003 号课程的学生姓名
可以写成:
πSname(σCpno='81003'(Course ⋈ SC ⋈ Student))
也可以写成等价的分步形式,例如先在 Course 中选出 Cpno='81003' 的课程,再与 SC、Student 连接。
思路
- 先找到“直接先行课为 81003”的课程;
- 再找出选了这些课程的学生;
- 最后投影学生姓名。
关键提醒
三表连接时要特别注意:
- 连接属性是否匹配;
- 中间结果是否保留了后续需要的属性;
- 运算顺序是否影响结果表达的清晰度。
虽然关系代数在逻辑上强调结果等价,但在书写和理解时,合理安排顺序更清晰。
2.13 本章核心概念的纵向串联
为了真正学懂这一章,需要把这些概念连起来理解。
2.13.1 从二维表到关系
你看到的一张表,并不一定是关系。
只有当它满足:
- 行可看作元组集合;
- 列对应属性;
- 行列无序;
- 元组不重复;
- 每个分量都是原子值;
它才是关系模型中的“关系”。
2.13.2 从关系到关系模式
关系模式规定:
- 这张表应有哪些属性;
- 各属性属于什么域;
- 哪些属性组成码;
- 要满足哪些约束。
而关系则是这个模式在某一时刻的具体数据。
2.13.3 从码到完整性
有码,才能唯一标识元组;
有主码,才能保证实体完整性;
有外码,才能建立关系之间的引用,并保证参照完整性。
所以:
- 主码解决“谁是谁”
- 外码解决“谁引用谁”
- 完整性约束解决“数据能不能这样填”
2.13.4 从关系操作到关系代数
关系操作告诉我们“能做什么”:
- 查哪些行
- 取哪些列
- 把哪些表连起来
- 取并、交、差
- 做“全部满足”这类查询
关系代数则把这些操作变成严格的形式化表达。
后面的 SQL,本质上就是这些思想的工程化实现。
2.14 本章易混点与重点辨析
2.14.1 关系 vs 关系模式
- 关系模式:表结构,静态描述
- 关系:表中数据,动态内容
2.14.2 主码 vs 候选码
- 候选码:所有可能的最小唯一标识
- 主码:从候选码中选出的一个
2.14.3 主属性 vs 非主属性
- 出现在任一候选码中的属性是主属性
- 不属于任何候选码的属性是非主属性
2.14.4 实体完整性 vs 参照完整性
- 实体完整性:主码不能为空
- 参照完整性:外码要么为空,要么引用已存在的主码值
2.14.5 选择 vs 投影
- 选择:按条件筛行
- 投影:按需要取列
一个是“横向切”,一个是“纵向切”。
2.14.6 等值连接 vs 自然连接
- 等值连接:保留两个参与比较的属性列
- 自然连接:自动按同名属性相等连接,并去掉重复公共列
2.14.7 差运算中的全集意识
做“没选某门课的学生”这种题时,要先想清楚:
- 差的左边到底是谁的全集?
若问“所有学生中谁没选”,左边就必须是 Student。
若左边选错,结果会漏人。
2.14.8 除运算的语义
除运算通常对应:
- 选修了全部课程
- 至少修过某一组指定课程中的全部
- 满足“对集合中的每个元素都成立”的查询
判断一条记录能否进入结果,关键看它的象集是否包含要求集合。
2.15 本章总结
本章是关系数据库理论的起点,核心内容可以概括为四部分:
1. 关系数据结构
掌握了:
- 域
- 笛卡尔积
- 关系
- 属性
- 元组
- 码
- 关系模式
- 关系数据库
- 关系模型的存储结构
2. 关系操作
掌握了:
- 查询操作:选择、投影、连接、除、并、交、差、笛卡尔积
- 数据更新:插入、删除、修改
3. 关系完整性约束
掌握了:
- 实体完整性
- 参照完整性
- 用户定义完整性
4. 关系代数
掌握了:
- 传统集合运算
- 专门的关系运算
- 用形式化方法表达查询
2.16 一句话总复盘
关系数据库的本质是:
用满足一定规范的二维表来表示数据,用集合运算来操作数据,用完整性约束来保证数据正确。
而关系代数,就是把这种操作方式严格、抽象地表达出来的理论工具。