第 2 章 · 关系模型与关系代数

关系模型胜在有数学根基;本章给出「关系」的严格定义与它的运算——关系代数。

2.1 关系、元组、属性、域

关系(Relation) 是一张表,但更严格:它是笛卡尔积的一个子集

  • 域(Domain):一组同类型值的集合,如 学号域 = {S001, S002, ...}
  • 元组(Tuple):表中的一行,各属性值的有序组合。
  • 属性(Attribute):表中的一列,给域起名。
  • 关系模式R(A1, A2, ..., An),如 Student(学号, 姓名, 系)

三条性质:列同质(每列来自同一域)、行无序、列无序(靠名字不靠位置)、不能有重复元组(集合语义,与 SQL 表的多重集语义不同)。

Student(学号, 姓名, 系)
┌──────┬──────┬────┐
│ S001 │ 张三 │ CS │   ← 一个元组
│ S002 │ 李四 │ EE │
└──────┴──────┴────┘
          ↑ 属性(域 = 所有合法学号)

2.2 码:候选码、主码、外码

  • 候选码(Candidate Key):能唯一标识一个元组的最小属性组,可能有多个。
  • 主码(Primary Key):从候选码中选一个作默认标识,不能为空
  • 外码(Foreign Key):属性 F 在本关系不是码、却是另一关系的码,用来引用另一张表。
Student(学号 PK, 姓名, 系)
SC(学号 FK, 课程号 FK, 成绩)   —— SC 的两个外码共同引用 Student 和 Course

{学号, 姓名} 也能唯一标识人,但去掉「姓名」仍唯一,故不是候选码——候选码不能有冗余属性。

2.3 三类完整性约束

约束规则违反示例
实体完整性主码不能取空值学生没有学号
参照完整性外码要么为空,要么等于被参照表某主码值选了不存在的课程号
用户定义完整性语义约束(取值范围等)成绩 < 0 或 > 100

实体完整性保证「每行能被找到」;参照完整性保证「引用不悬空」。两者由 DBMS 自动强制,即第 3 章的 PRIMARY KEY/FOREIGN KEY

2.4 关系代数:五种基本运算

关系代数:输入/输出仍是关系的集合运算。常用运算:

运算记号作用
选择 σσ条件(R)\sigma_{\text{条件}}(R)(按条件过滤元组)
投影 ππ属性(R)\pi_{\text{属性}}(R)(去重)
连接 ⋈RR.A=S.BSR \bowtie_{R.A=S.B} S按条件拼两个关系
除 ÷R÷SR \div S找「满足 S 全部」的元组
并 ∪ / 交 ∩ / 差 −集合运算要求两关系结构相容
σ_{系='CS'}(Student)          → 只保留 CS 的学生行
π_{姓名}(Student)             → 只剩「姓名」一列,且去重
Student ⋈_{学号=学号} SC      → 学生和选课按学号拼成宽表

连接最贵也最常用,等价于「先笛卡尔积,再选择」;第 4 章内/外连接、第 9 章连接优化源头在此。

除(÷):SC ÷ Course 求「选了所有课程的学生」,专门回答「对全部的…」类查询。

对比:关系代数 vs 关系演算——关系代数过程式,明确写「先选谁、再连谁」,对应 SQL 执行顺序;关系演算(元组/域演算)声明式,只描述「满足条件的元组」,是 SQL WHERE 的灵感。二者表达能力等价,SQL = 代数内核 + 演算外观。

对比:关系 vs 非关系——关系模型靠表和值匹配表达联系,强在一致性与复杂查询;非关系(文档、KV、图,见第 10 章)放弃部分一致性换扩展性。