返回 Database
Database 2026-05-19

第2章 关系数据库

第2章 关系数据库

2.1 本章总览

本章围绕关系模型展开,核心任务是回答四个问题:

  1. 关系数据库中的数据长什么样:用二维表表示数据,即“关系”。
  2. 关系数据库中的数据如何操作:查询、插入、删除、修改。
  3. 关系数据库中的数据要满足什么约束:实体完整性、参照完整性、用户定义完整性。
  4. 关系查询如何形式化表达:用关系代数描述查询过程。

从学习路径上看,本章可以概括为:

  • 先掌握关系模型的数据结构
  • 再理解关系操作与关系语言
  • 接着掌握完整性约束
  • 最后学习关系代数,为后续 SQL 学习打基础。

2.2 关系模型的数据结构及形式化定义

2.2.1 关系模型的核心特征

关系模型有三个非常重要的特点:

  1. 单一的数据结构——关系

    • 现实世界中的实体以及实体之间的联系,都用关系表示。
    • 从用户视角看,关系就是一张二维表
  2. 建立在集合论基础上

    • 关系中的数据本质上是集合中的元素。
    • 因此,关系中的行、列顺序通常都不是本质属性。
  3. 以集合操作为主要操作方式

    • 查询和更新都以“集合”为单位进行,而不是逐条记录处理。

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 称为关系的

关系的本质

关系不是全部可能组合,而是有实际语义的组合集合

关系中的基本概念

  1. 关系

    • 笛卡尔积的一个有意义的子集。
  2. 元组

    • 关系中的每个元素称为元组,通常记为 t
  3. 属性

    • 关系中每一列称为一个属性。
  4. 关系的表示

    • 关系通常用二维表表示。
    • 表中的每一行对应一个元组。
    • 表中的每一列对应一个属性。

三类关系

  1. 基本关系(基本表、基表)

    • 实际存储在数据库中的表。
  2. 查询结果

    • 查询执行后临时产生的结果表。
  3. 视图表

    • 由基本表或其他视图导出的虚表。
    • 视图本身通常不存储实际数据。

2.2.5 基本关系的性质

基本关系必须满足以下性质:

  1. 列是同质的

    • 同一列中的值必须来自同一个域。
    • 也就是说,同一属性的数据类型和语义应一致。
  2. 不同列可以来自同一个域

    • 例如“学号”和“班长学号”都可以来自学号域。
    • 但属性名必须不同,以区分含义。
  3. 列的顺序无关

    • 列交换顺序后,关系本质不变。
  4. 任意两个元组不能完全相同

    • 关系中不允许出现重复元组。
  5. 行的顺序无关

    • 行交换顺序后,关系本质不变。
  6. 分量必须是原子值

    • 每个属性值都必须不可再分。
    • 这是规范化关系最基本的要求。

理解要点

关系本质上是一个集合,而不是 Excel 那种“看起来像表”的普通表格。
因此:

  • 集合中元素无序,所以行无序;
  • 属性位置无本质区别,所以列无序;
  • 集合中不允许重复元素,所以元组不能重复;
  • 原子性要求一个单元格里不能再嵌套一个表或列表。

补充

满足这些规范条件的关系称为规范化关系,简称属于某种范式(Normal Form, NF)。范式的详细内容通常在后续章节学习。


2.3 关系模式

2.3.1 什么是关系模式

关系模式是对关系的结构性描述,它回答的是:

  • 这个关系有哪些属性;
  • 每个属性来自什么域;
  • 属性之间有什么约束;
  • 这些属性如何组织成一个关系。

关系模式描述的内容

  1. 元组集合的结构

    • 属性由哪些字段构成
    • 属性来自哪些域
    • 属性和域之间的映射关系
  2. 完整性约束条件

    • 比如主码不能为空
    • 外码必须引用已存在的主码值

关键理解

  • 关系模式是“型”
  • 关系是“值”

可以类比为:

  • 类定义 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)

定义

若关系模式中的某一个属性或属性组的值能够唯一标识一个元组,并且它的任何真子集都不能唯一标识元组,则该属性或属性组称为候选码

理解要点

候选码必须满足两个条件:

  1. 唯一性

    • 能唯一确定一条记录。
  2. 最小性

    • 去掉其中任何一个属性后,就不能保证唯一。

例子

在学生表中:

  • 学号 能唯一标识一个学生;
  • 且再去掉就没了,因此 学号 是候选码。

如果某个关系中要靠 (学号, 课程号) 组合才能唯一标识一条记录,那么这个属性组就是候选码。


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 可以不同。

两种常见思路

  1. 一个表对应一个操作系统文件

    • 由操作系统完成底层文件组织。
  2. 数据库系统自行管理大文件空间

    • 数据库系统先向操作系统申请大文件;
    • 再自行划分存储空间;
    • 组织表、索引等存储结构;
    • 完成自己的存储管理。

理解要点

  • 关系模型强调的是逻辑结构
  • 物理实现可以千差万别;
  • 用户日常操作主要面对的是逻辑层,而不是物理存储细节。

2.6 关系操作

2.6.1 常用关系操作

关系操作分为两大类:

1. 查询操作

包括:

  • 选择
  • 投影
  • 连接
  • 笛卡尔积

其中通常把以下五种看作基本操作:

  • 选择
  • 投影
  • 笛卡尔积

2. 数据更新操作

包括:

  • 插入
  • 删除
  • 修改

2.6.2 关系操作的特点

1. 集合操作方式

关系操作的对象和结果都是集合,因此通常是“一次处理一个集合”。

2. 封闭性

关系操作的输入和输出都是关系。

这意味着:

  • 操作对象是关系;
  • 中间结果还是关系;
  • 最终结果仍然是关系。

理解要点

正因为“结果仍然是关系”,所以关系操作可以层层嵌套、连续组合
这也是 SQL 能写复杂查询的基础。


2.6.3 关系数据库语言的分类

关系数据库语言大体可以分为三类:

1. 关系代数语言

代表:ISBL

特点:

  • 以运算为中心;
  • 通过一系列关系运算构造查询。

2. 关系演算语言

分为:

  • 元组关系演算
    • 代表:ALPHAQUEL
  • 域关系演算
    • 代表:QBE

特点:

  • 以逻辑描述为中心;
  • 描述“满足什么条件的数据要被找出来”。

3. 结构化查询语言 SQL

SQL 同时具有:

  • 关系代数的运算思想
  • 关系演算的描述思想

因此它是最常用、最实用的关系数据库语言。


2.7 关系的完整性

完整性约束用于保证数据正确、有效、一致

关系模型中主要有三类完整性约束:

  1. 实体完整性
  2. 参照完整性
  3. 用户定义的完整性

其中:

  • 实体完整性和参照完整性是关系模型必须满足的基本约束;
  • 用户定义完整性是具体业务语义提出的约束。

2.7.1 实体完整性

规则

若属性 A 是基本关系 R 的主属性,则属性 A 不能取空值

这条规则称为实体完整性规则(Entity Integrity)

为什么主码不能空

主码的作用是唯一标识元组。
如果主码为空,那么:

  • 无法区分这条记录是谁;
  • 无法唯一标识实体;
  • 也无法作为其他关系引用的目标。

例子

关系:

选修(学号, 课程号, 成绩)

(学号, 课程号) 是主码,那么:

  • 学号 不能空;
  • 课程号 不能空。

空值的含义

空值不等于 0,也不等于空字符串。
空值一般表示:

  • 不知道
  • 不存在
  • 无意义

一句话理解

主码不能为空,是为了保证每个元组都能被明确识别。


2.7.2 参照完整性

参照完整性描述的是关系之间引用的一致性

外码(Foreign Key)的定义

F 是基本关系 R 的一个或一组属性,但 F 不是关系 R 的码。
如果 F 与基本关系 S 的主码 Ks 相对应,则称 FR外码

其中:

  • R 称为参照关系(Referencing Relation)
  • S 称为被参照关系(Referenced Relation)

说明

  1. RS 不一定是不同的关系。

    • 也就是说,一个关系可以引用自己。
    • 例如课程表中的“先修课”引用课程表自身的主码“课程号”。
  2. 外码与被参照主码必须定义在同一个域上,或在一组对应域上。

  3. 外码和主码未必同名,但在设计中通常会尽量同名,便于理解。


参照完整性规则

若属性(组)F 是关系 R 的外码,它与关系 S 的主码 Ks 相对应,则对于 R 中每个元组,F 上的值必须满足:

  1. 要么取空值

    • 且若是属性组,则组内每个属性都应为空;
  2. 要么等于 S 中某个元组的主码值

直观解释

外码的值只能来自两个来源:

  • 被参照表中已经存在的主码值

不能凭空写一个数据库中根本不存在的值。


例子 1:学生与专业

关系:

  • 学生(学号,姓名,性别,出生日期,主修专业)
  • 专业(专业名,专业编号)

学生.主修专业 引用 专业.专业名,则:

  • 可以为空,表示尚未分配专业;
  • 若不为空,则必须等于专业表中某个已存在的“专业名”。

不能出现一个根本不存在的专业。


例子 2:学生、课程与选课

关系:

  • 学生(学号,姓名,性别,出生日期,主修专业)
  • 课程(课程号,课程名,学分,先修课)
  • 学生选课(学号,课程号,成绩,选课学期,教学班)

此时:

  • 学生选课.学号 是外码,引用 学生.学号
  • 学生选课.课程号 是外码,引用 课程.课程号

由于 学号课程号 在选课关系中通常又属于主码,因此它们:

  • 作为主属性,不能取空值
  • 作为外码,又必须引用已存在的学生和课程。

这说明一个属性可以同时受到实体完整性参照完整性的约束。


例子 3:课程的先修课

关系:

课程(课程号,课程名,学分,先修课)

其中:

  • 先修课 可以为空,表示该课程没有先修课;
  • 若不为空,则必须等于课程表中某个已存在的 课程号

这是一个自引用外码的典型例子。


2.7.3 用户定义的完整性

用户定义完整性是针对某个具体应用场景所提出的约束,反映的是业务语义要求。

特点

  • 与具体业务有关;
  • 不是关系模型固定规定的;
  • 由数据库系统提供定义和检查机制。

例子

关系:

课程(课程号,课程名,学分)

可能要求:

  1. 课程号 必须唯一
  2. 课程名 不能为空
  3. 学分 只能取 {1, 2, 3, 4}

这些约束不属于实体完整性或参照完整性的标准规则,但它们对业务是必要的,因此属于用户定义完整性。

常见形式

  • NOT NULL
  • UNIQUE
  • CHECK
  • 默认值
  • 触发器或更复杂业务规则

2.8 关系代数

2.8.1 什么是关系代数

关系代数是一种抽象的查询语言,它通过对关系进行运算来表达查询。

两个核心特征

  1. 运算对象是关系
  2. 运算结果仍然是关系

运算符分类

关系代数的运算符分为两类:

  1. 传统集合运算符
  2. 专门的关系运算符

其中:

  • 传统集合运算主要从“行”的角度处理关系;
  • 专门的关系运算既涉及“行”,也涉及“列”。

2.8.2 关系代数运算符总览

传统集合运算符

  • :并
  • -:差
  • :交
  • ×:笛卡尔积

专门的关系运算符

  • σ:选择
  • π:投影
  • :连接
  • ÷:除

2.9 传统的集合运算

2.9.1 并(Union)

定义

R ∪ S 表示属于 R 或属于 S 的元组组成的关系。

形式化表示:

R ∪ S = { t | t ∈ R ∨ t ∈ S }

前提条件

并运算要求 RS 并相容,即:

  1. 具有相同的目 n
  2. 对应属性来自相同的域

理解

并运算就是把两个同构关系中的元组合并,并自动去重。


2.9.2 差(Difference)

定义

R - S 表示属于 R 但不属于 S 的元组组成的关系。

形式化表示:

R - S = { t | t ∈ R ∧ t ∉ S }

前提条件

同样要求 RS 并相容。

理解

差运算就是“从 R 中删去那些也在 S 中出现的元组”。


2.9.3 交(Intersection)

定义

R ∩ S 表示既属于 R 又属于 S 的元组组成的关系。

形式化表示:

R ∩ S = { t | t ∈ R ∧ t ∈ S }

并且可以由差运算表示为:

R ∩ S = R - (R - S)

前提条件

仍要求 RS 并相容。


2.9.4 笛卡尔积(Product)

定义

设:

  • Rn 目关系,有 k1 个元组;
  • Sm 目关系,有 k2 个元组;

则:

R × S 是一个 (n + m) 列的关系,共有 k1 × k2 个元组。

结果的组成

  • n 列来自 R 的一个元组;
  • m 列来自 S 的一个元组。

理解

笛卡尔积会把两个关系的每个元组两两配对。
因此结果通常会很大,并且很多组合没有实际意义。
后续常结合“选择”来筛出真正有意义的组合。


2.10 专门的关系运算前的记号

在学习选择、投影、连接、除之前,需要掌握几个记号。

2.10.1 元组与分量记号

设关系模式为:

R(A1, A2, …, An)

并设 R 是该模式的一个关系,则:

  • t ∈ R 表示 tR 的一个元组
  • t[Ai] 表示元组 t 在属性 Ai 上的分量

2.10.2 属性组记号

若:

A = {Ai1, Ai2, …, Aik}

其中 Ai1, Ai2, …, AikA1, A2, …, An 的一部分,则 A 称为属性列属性组

此时:

t[A] = (t[Ai1], t[Ai2], …, t[Aik])

表示元组 t 在属性组 A 上的分量集合。

Ā 表示从 {A1, A2, …, An} 中去掉属性组 A 后剩余的属性组。


2.10.3 元组的连接

若:

  • tr ∈ R
  • ts ∈ S

tr ts 称为元组的连接,表示把两个元组拼接成一个新元组。

如果:

  • Rn 元组
  • Sm 元组

tr ts 是一个 n + m 列的元组:

  • n 个分量来自 R
  • m 个分量来自 S

2.10.4 象集(Image Set)

给定关系:

R(X, Z)

其中 XZ 为属性组。
t[X] = x 时,xR 中的象集定义为:

Zx = { t[Z] | t ∈ R, t[X] = x }

含义

它表示:

在关系 R 中,属性组 X 上取值为 x 的那些元组,在属性组 Z 上的取值集合。

例子

若关系 R(X, Z) 中有:

  • x1 对应 Z1, Z2, Z3
  • x2 对应 Z2, Z3
  • x3 对应 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 }

其中 AR 中的属性列或属性组。

作用

投影是“按列取数据”。

直观理解

  • 投影处理列
  • 只保留想要的属性
  • 可理解成 SQL 中的 SELECT 某些列

例子 1

查询学生的姓名和主修专业:

πSname, Smajor(Student)

例子 2

查询学生关系中都有哪些专业:

πSmajor(Student)

关键点:投影会去重

因为关系是集合,所以投影后的重复元组会被自动消除。

例如多个学生都来自“计算机科学与技术”,投影 Smajor 后只保留一个“计算机科学与技术”。

一句话理解

投影就是:

从表中抽取指定列,并自动去重。


2.11.3 连接(Join)

连接用于把两个关系中有关联的元组组合起来。

常见两类连接

  1. 等值连接
  2. 自然连接

1. 等值连接

等值连接是先做笛卡尔积,再选出两个关系中某些属性值相等的元组。

例如:

R ⋈_{R.B = S.B} S

其思想相当于:

  1. 先做 R × S
  2. 再保留满足 R.B = S.B 的元组

特点

  • 相等条件两边的属性通常都会保留;
  • 因此结果中可能同时出现 R.BS.B 两列。

2. 自然连接

自然连接是在等值连接基础上的进一步简化:

  • 自动以两个关系中的同名属性相等为连接条件;
  • 并在结果中去掉重复的公共属性列。

记作:

R ⋈ S

特点

  • 更简洁
  • 结果更自然
  • 常用于关系模式中具有公共属性的情况

悬浮元组(Dangling Tuple)

在自然连接时,若关系 R 中某些元组在 S 中找不到公共属性值相等的对应元组,那么这些元组会被舍弃。被舍弃的元组称为悬浮元组

直观理解

自然连接默认只保留“能对上号”的元组。
对不上号的就丢掉,这些被丢掉的就是悬浮元组。


外连接(Outer Join)

如果希望把悬浮元组也保留下来,并把匹配不到的属性填空值 NULL,这种连接称为外连接

包括:

  1. 左外连接

    • 保留左关系的全部元组;
    • 右边匹配不到的补 NULL
  2. 右外连接

    • 保留右关系的全部元组;
    • 左边匹配不到的补 NULL
  3. 全外连接

    • 两边所有元组都保留;
    • 哪边匹配不到,哪边补 NULL

理解要点

  • 自然连接:只保留成功匹配的
  • 外连接:把没匹配上的也保留

2.11.4 除运算(Division)

除运算是关系代数中最难理解、但非常重要的运算之一。

基本形式

给定:

  • R(X, Y)
  • S(Y, Z)

其中 X、Y、Z 为属性组。
R 中的 YS 中的 Y 可以名字不同,但必须来自相同的域集。

R ÷ S 的结果是一个新的关系 P(X)

形式化定义

PR 中满足下列条件的元组在 X 属性列上的投影:

R ÷ S = { tr[X] | tr ∈ R ∧ πY(S) ⊆ Yx }

其中:

  • x = tr[X]
  • YxxR 中的象集

直观含义

除运算的核心意思是:

找出那些在 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))

解释

  1. 先从 SC 中选出课程号为 81002 的元组;
  2. 再投影出学号列。

2.12.2 查询没有选修 81002 号课程的学生学号

关系代数表达式:

πSno(Student) - πSno(σCno='81002'(SC))

解释

  1. πSno(Student) 得到所有学生学号;
  2. πSno(σCno='81002'(SC)) 得到选了 81002 的学生学号;
  3. 两者相减,得到没选该课的学生学号。

易错点

不能写成:

πSno(SC) - πSno(σCno='81002'(SC))

因为 πSno(SC) 只包含“至少选过一门课的学生”,会漏掉从未选课的学生。
题目问的是“所有学生中没有选修 81002 的人”,因此左边必须从 Student 出发。


2.12.3 查询至少选修了 81001 号课程和 81003 号课程的学生号码

思路

先建立一个临时关系:

K(Cno) = {81001, 81003}

再计算:

πSno, Cno(SC) ÷ K

含义

找出那些学号 Sno,使得它对应的课程集合至少包含 8100181003

结果语义

结果是“同时选过 81001 和 81003 的所有学生学号”。


2.12.4 查询选修了全部课程的学生号码和姓名

关系代数表达式可写为:

πSno, Cno(SC) ÷ πCno(Course) ⋈ πSno, Sname(Student)

思路拆解

  1. πCno(Course):取出所有课程号,作为“全部课程集合”;
  2. πSno, Cno(SC) ÷ πCno(Course):找出选修了全部课程的学生学号;
  3. 再与 πSno, Sname(Student) 连接,得到姓名。

本质

这是“全部”类查询,最典型地适合用除运算表示。


2.12.5 查询至少选修了一门其直接先行课为 81003 号课程的学生姓名

可以写成:

πSname(σCpno='81003'(Course ⋈ SC ⋈ Student))

也可以写成等价的分步形式,例如先在 Course 中选出 Cpno='81003' 的课程,再与 SCStudent 连接。

思路

  1. 先找到“直接先行课为 81003”的课程;
  2. 再找出选了这些课程的学生;
  3. 最后投影学生姓名。

关键提醒

三表连接时要特别注意:

  • 连接属性是否匹配;
  • 中间结果是否保留了后续需要的属性;
  • 运算顺序是否影响结果表达的清晰度。

虽然关系代数在逻辑上强调结果等价,但在书写和理解时,合理安排顺序更清晰。


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 一句话总复盘

关系数据库的本质是:
用满足一定规范的二维表来表示数据,用集合运算来操作数据,用完整性约束来保证数据正确。

而关系代数,就是把这种操作方式严格、抽象地表达出来的理论工具。