关系数据库

关系数据库中名词术语之间的对应关系:

关系模型理论 关系数据库管理系统(SQL) 文件系统
关系 relation 表 table 文件 set of records
属性 attribute 列 column 字段 field
元组 tuple 行 row 记录 record
关系模式 schema 表头 table heading 记录型 type of record
码 key 主码 primary key -
候选码 candidate key 唯一码 unique -

关系数据结构及形式化定义

域(Domain)

(Domain)是具有相同数据类型的值的集合

示例:

  • 整数、实数
  • 特定范围整数:[18, 60]
  • 字符串集合:char(25)
  • 枚举类型:{ '男', '女' }

同一域中元素互不相同。

笛卡尔积

给定域 {D1,D2,...,Dn}\left\lbrace D_1,D_2,...,D_n \right\rbrace,其笛卡尔积为:

D1×D2×...×Dn={(d1,d2,...,dn)diDi,i=1,2,...,n}D_1 \times D_2 \times ... \times D_n = \{(d_1,d_2,...,d_n) \mid d_i \in D_i, i=1,2,...,n\}

特性:

  • 每个元素称为 nn 元组
  • 基数计算:若各域基数分别为 m1,m2,...,mnm_1,m_2,...,m_n,则总基数为 i=1nmi\displaystyle \prod_{i=1}^{n} m_i

关系(Relation)

  • 关系(Relation):逻辑上表示为二维表,数学上定义为笛卡尔积的子集。
  • 元组(Tuple):表中的一行,代表一个具体的记录。
  • 属性(Attribute):表中的一列,对应某一特定字段。
  • (Domain):属性值的取值范围,例如性别属性的域可以是「男, 女」。

符号约定

  • 关系用大写字母 R R 表示。
  • 元组用小写字母 t t 表示。
  • 属性A1,A2,,An A_1, A_2, \dots, A_n 表示。
  • D1,D2,,Dn D_1, D_2, \dots, D_n 表示。

关系可以有三种类型:

  • 基本关系(基本表基表):实际存在的表,是实际存储数据的逻辑表示。
  • 查询表:查询结果对应的表,结果数据不需要持久存储。
  • 视图表:由基本表或其他视图表导出的表,是虚表,结果数据也不需要持久存储。

查询表与视图表的区别

两者都有对应的数据库查询操作,但查询表对应的查询请求不需要保存在数据库中,而视图表对应的查询请求需要持久保存在数据库中。

说明:

  1. 上面所说的「表」的概念,一般只在关系数据库管理系统(即 SQL 语言)中使用
  2. 关系模型是一种逻辑数据模型,不涉及数据的物理存储,在关系模型理论中,其数据结构只有「关系」
  3. 在关系模型上进行数据操纵,其操作结果也构成一个「关系」(也可以通俗地称为「结果关系」「临时关系」或「中间关系」)

关系可以是一个无限集合,定义关系的笛卡尔积不满足交换律。因此使用「关系」来作为关系数据模型的数据结构时,需添加约束「关系是一个有限子集」与「笛卡尔积满足交换律」。

从而关系模型数据结构的「关系」具有以下性质:

  1. 列同质性:每一列中的分量来自同一个域,且具有相同的数据类型。
  2. 属性唯一性:每个属性必须有唯一的名称,即使不同属性可能共享相同的域。
  3. 列无序性:属性的排列顺序无关紧要,可以通过属性名访问特定列。
  4. 行唯一性:任意两个元组在候选码上的取值不能相同。
  5. 行无序性:元组的排列顺序无关紧要,可通过指定条件访问特定行。
  6. 原子性:每个分量必须是不可再分的最小数据项。

码的分类与作用

(Key)是关系中用于唯一标识元组的属性或属性组,分为以下几类:

  • 候选码(Candidate Key):能唯一标识元组的最小属性组,简称
  • 主码(Primary Key):从候选码中选出的一个作为主码。
  • 外码(Foreign Key):引用其他关系主码的属性。
  • 全码(All-Key):当所有属性共同构成候选码时称为全码。

每个关系至少有一个候选码,这是关系模型的基本特性。

候选码中的诸属性称为该关系的主属性(prime attribute)。不包含在任何候选码中的属性称为非主属性(non-prime attribute)。

数据完整性约束

关系模型定义了三类完整性约束,以确保数据的正确性和一致性:

  1. 实体完整性(Entity Integrity):主码中的属性不能取空值,且主码值必须唯一。2. 参照完整性(Referential Integrity):外码要么为空,要么必须引用被参照关系中已存在的主码值。
  2. 用户定义完整性(User-Defined Integrity):根据具体应用需求定义的约束条件,例如非空、唯一性或取值范围。

实体完整性

  • 规则:主码中的属性不能取空值(NULL),且主码值必须唯一。
  • 目的:保证每个元组的唯一性。
  • 示例
    1
    2
    3
    4
    5
    6
    CREATE TABLE Students (
    学号 INT PRIMARY KEY, -- 整数类型;主码:唯一非空
    姓名 VARCHAR(50) NOT NULL, -- 可变长度字符串,最多 50 字符;非空
    性别 CHAR(1), -- 固定长度字符串,1 字符
    年龄 INT
    );

参照完整性

  • 规则:外码(Foreign Key)要么为空,要么必须引用被参照关系中已存在的主码值。
  • 目的:维护关系间的引用一致性。
  • 示例
    1
    2
    3
    4
    5
    6
    7
    CREATE TABLE Enrollments (
    学号 INT,
    课程号 INT,
    成绩 DECIMAL(4,2), -- 小数类型,总位数 4 位,小数 2 位
    FOREIGN KEY (学号) REFERENCES Students(学号), -- 学号必须存在于 Students 表中,或为空
    FOREIGN KEY (课程号) REFERENCES Courses(课程号) -- 课程号必须存在于 Courses 表中,或为空
    );

用户定义完整性

  • 规则:根据具体应用需求定义的约束条件,例如非空、唯一性或取值范围。
  • 示例
    1
    2
    3
    4
    5
    CREATE TABLE Courses (
    课程号 INT PRIMARY KEY,
    课程名 VARCHAR(100) UNIQUE, -- 唯一(候选码)
    学分 INT CHECK (学分 BETWEEN 1 AND 4) -- 取值范围(微积分:你好)
    );

关系模式与关系实例

  • 关系模式(Relation Schema):描述关系的结构,包括属性集合、域及完整性约束。
    • 形式化表示:R(U,D,DOM,F) R(U, D, \mathrm{DOM}, F)
      • R R :关系名
      • U U :属性集合
      • D D :域集合
      • DOM \mathrm{DOM} :属性到域的映射
      • F F :完整性约束条件
  • 关系实例(Relation Instance):某一时刻关系的具体内容,即元组集合。

关系模式通常可以简记为 R(U)R(U)R(A1,A2,,An)R(A_1, A_2, \dots, A_n),其中 AiA_i 为属性名,UU 为属性名集合,RR 为关系名。

关系操作

关系模型支持两类基本操作:查询和更新。这些操作可以进一步分解为以下五种基本关系操作:

  1. 选择(Selection):从关系中筛选符合条件的元组。
  2. 投影(Projection):从关系中提取指定的属性列。
  3. 笛卡尔积(Cartesian Product):生成两个关系的所有组合。
  4. (Union):合并两个关系的元组集合。
  5. (Difference):从一个关系中移除另一个关系的元组。
graph TD
    A[关系操作] --> B[查询操作]
    A --> C[更新操作]
    B --> D[选择]
    B --> E[投影]
    B --> F[连接]
    C --> G[插入]
    C --> H[删除]
    C --> I[修改]

关系代数

概述

核心概念

关系代数(Relational Algebra)是一种抽象的查询语言,用关系运算表达对关系的操作:

  • 运算对象和结果均为关系
  • 包含集合运算和专门关系运算
  • 表达式可表示数据查询、插入、删除和修改

运算分类

graph TD
    A[关系运算] --> B[集合运算]
    A --> C[专门关系运算]
    B --> D[并/差/交/笛卡尔积]
    C --> E[选择/投影/连接/除]

关键特性

  • 集合操作:操作对象和结果都是元组集合
  • 基本运算:并、差、笛卡尔积、选择、投影
  • 运算符要求:需同时掌握执行条件和结果模式

基本运算体系

集合运算

  • 并运算(Union)
    • 前提条件:同类关系(同目且属性域相同)
    • 数学表达:RS={ttRtS}R \cup S = \{ t \mid t \in R \lor t \in S \}
    • 操作符:R union S
    • 特性:交换律、结合律
    • SQL 例子:
      1
      2
      3
      4
      5
      -- 选出所有选修了「数据库」或「数据结构」课程的学生
      -- SC (Student Course) 表示学生选课关系表(学号,课程号)
      SELECT 学号 FROM SC WHERE 课程号 = '数据库'
      UNION
      SELECT 学号 FROM SC WHERE 课程号 = '数据结构';
  • 差运算(Difference)
    • 数学表达:RS={ttRtS}R - S = \{ t \mid t \in R \land t \notin S \}
    • 操作符:R except S
    • 典型应用:排除特定数据
    • SQL 例子:
      1
      2
      3
      4
      -- 选出所有选修了「数据库」但未选修「数据结构」课程的学生
      SELECT 学号 FROM SC WHERE 课程号 = '数据库'
      EXCEPT
      SELECT 学号 FROM SC WHERE 课程号 = '数据结构';
  • 笛卡尔积(Cartesian Product)
    • 结果模式:n+mn+m 列关系
    • 数学表达:R×S={(tr,ts)trRtsS}R \times S = \{ (t_r,t_s) | t_r \in R \land t_s \in S \}
    • 操作符:R product S
    • 注意:同名属性需重命名
    • SQL 例子:
      1
      2
      -- 选出所有学生选修的课程
      SELECT * FROM Students, SC WHERE Students.学号 = SC.学号;

专门关系运算

  • 选择(Selection)
    • 前提条件:选择条件 FF 是一个只能由关系属性名、常量、运算符组成的逻辑表达式
    • 数学表达:σF(R)={ttRF(t)=True}\sigma_F(R) = \{ t \mid t \in R \land F(t) = \mathrm{True} \}
    • 操作符:R where F
    • 执行逻辑:
      1
      2
      3
      4
      result = []
      for t in R:
      if F(t) == True:
      result.append(t) # 修改为将符合条件的元组添加到结果列表
    • SQL 例子
      1
      2
      -- 选出所有年龄大于 18 岁的学生
      SELECT * FROM Students WHERE 年龄 > 18;
  • 投影(Projection)
    • 前提条件:属性集合 A1,A2,,AnA_1, A_2, \dots, A_n 是关系 RR 的属性集的子集
    • 数学表达:πA1,...,An(R)={t[A1,...,An]tR}\pi_{A_1,...,A_n}(R) = \{ t[A_1,...,A_n] \mid t \in R \}
    • 操作符:R[A1, A2, …, An]
    • 去重机制:自动消除重复元组
    • SQL 例子:
      1
      2
      -- 选出所有学生的学号和姓名
      SELECT 学号, 姓名 FROM Students;

记号系统与核心概念

符号 含义
A,B,C,,A1,A2,A, B, C, \dots, A_1, A_2, \dots 大写字母表示属性名,小写字母表示属性值。例如:用 AA 表示属性名,用 aaa1,a2,a_1, a_2, \dots 表示属性 AA 的值
X,Y,Z,X, Y, Z, \dots 大写字母表示关系中的一个属性组/属性集
R,S,T,R, S, T, \dots 大写字母表示关系名,代表一个关系,或该关系的一个实例
R(U)R(U) 关系模式:关系名 RR, 关系中的属性集合 UU
r,s,t,,r1,r2,r, s, t, \dots, r_1, r_2, \dots 关系中的元组
r1[A]r_1[A] 元组 r1r_1 在属性(集)AA 上的取值

设关系模式为 R(A1,A2,,An)R(A_1, A_2, \dots, A_n)

  • 它的一个关系(实例)设为 RR
  • tRt \in R 表示 ttRR 中的一个元组
  • t[Ai]t[A_i] 表示元组 tt 中相应于属性 AiA_i 的一个分量(元组 tt 在属性 AiA_i 上的值)
  • A={Ai1,Ai2,,Aik}A = \left\lbrace A_{i_1}, A_{i_2}, \dots, A_{i_{k}} \right\rbrace,其中 Ai1,Ai2,,AikA_{i_1}, A_{i_2}, \dots, A_{i_{k}} 是来自于 A1,A2,,AnA_1, A_2, \dots, A_n 中的属性,则 AA 称为「属性列」或「属性组」或「属性集」。
  • t[A]=(t[Ai1],t[Ai2],,t[Aik])t[A] = (t[A_{i_1}], t[A_{i_2}], \dots, t[A_{i_{k}}]) 表示元组 tt 在属性组 AA 上诸分量的集合。
  • Aˉ\bar{A} 则表示从 {A1,A2,,An}\left\lbrace A_1, A_2, \dots, A_n \right\rbrace 中去掉 {Ai1,Ai2,,Aik}\left\lbrace A_{i_1}, A_{i_2}, \dots, A_{i_{k}} \right\rbrace 后剩余的属性组。

元组连接

元组连接:设 RRnn 目关系,SSmm 目关系,令 trR,tsSt_r \in R, t_s \in S,则 trts\overgroup{t_r t}_s 表示来自不同关系的元组拼接。

  • 这是一个 n+mn+m 列的元组,前 nn 列来自 RR 中元组 trt_r,后 mm 列来自 SS 中元组 tst_s
  • 可简记为 (tr,ts)(t_r, t_s)

象集

象集(Image Set):给定一个关系 R(X,Z)R(X, Z),其中 X,ZX, Z 为属性组,xx 为属性组 XX 定义域上的一个值,xxRR 中的象集定义为 Zx={t[Z]tRt[X]=x}Z_x = \{ t[Z] \mid t \in R \land t[X] = x \},表示 RR 中属性组 XX 上值为 xx 的元组在属性组 ZZ 上的值集合。

假设有一张订单表(相当于关系 RR):

订单号(XX 菜品(ZZ 数量
1001 汉堡 2
1001 薯条 3
1002 炸鸡 1
1003 汉堡 1
1003 薯条 2
  • XX 属性组 = 订单号(单一属性)
  • ZZ 属性组 = 菜品 + 数量(组合属性)

现在要查询订单号 1001 对应的所有菜品和数量,这就是象集的典型应用场景。

象集生成过程:

  1. 过滤:在订单表中筛选出 X=1001X=1001 的元组
    订单号(XX 菜品(ZZ 数量
    1001 汉堡 2
    1001 薯条 3
  2. 投影:提取这些元组的 ZZ 属性(菜品 + 数量)
    菜品(ZZ 数量
    汉堡 2
    薯条 3
  3. 结果:这个投影结果就是订单号 1001 的象集 Z1001={(汉堡,2),(薯条,3)}Z_{1001} = \{ (汉堡, 2), (薯条, 3) \}

对应 SQL 查询语句:

1
2
SELECT 菜品, 数量 FROM Orders
WHERE 订单号 = 1001;

象集的本质:相当于数据库中的「条件投影」操作。可以理解为——当我们要回答「某个 XX 值对应的 ZZ 值有哪些?」这类问题时,就是在求象集。

关系模式语义

  • 同名同义原则:属性名相同则语义与域相同
  • 重命名机制:通过赋值运算解决异名同义问题

扩展运算

交运算

交运算(Intersection)是关系代数中的一种集合运算,用于找出两个关系中共有的元组。

  • 前提条件:两个关系必须是同类关系
    • 具有相同的目(属性数量相同)
    • 对应属性取自同一个域
  • 数学表达:RS={ttRtS} R \cap S = \{ t \mid t \in R \land t \in S \}
  • 操作符:R intersect S
  • 特性:
    • 满足交换律:RS=SR R \cap S = S \cap R
    • 满足结合律:(RS)T=R(ST)(R \cap S) \cap T = R \cap (S \cap T)
  • 实现方式:交运算可以通过差运算实现

    RS=R(RS)=S(SR)R \cap S = R - (R - S) = S - (S - R)

假设我们有两个表,分别记录了两场派对的参与者名单:

  • 派对 A 的参与者名单:
姓名 年龄 性别
小明 20
小红 22
小刚 21
  • 派对 B 的参与者名单:
姓名 年龄 性别
小红 22
小丽 23
小刚 21

计算过程:

  1. RS R - S : 只参加派对 A 的人
    姓名 年龄 性别
    小明 20
  2. SR S - R : 只参加派对 B 的人
    姓名 年龄 性别
    小丽 23
  3. 最终交集 RS R \cap S : 同时参加了两场派对的人
    姓名 年龄 性别
    小红 22
    小刚 21

SQL 语句示例:

1
2
3
4
-- 查询同时喜欢苹果和香蕉的学生学号
SELECT 学号 FROM 喜欢水果 WHERE 水果 = '苹果'
INTERSECT -- 交集运算
SELECT 学号 FROM 喜欢水果 WHERE 水果 = '香蕉';

连接运算

连接运算是关系代数中的重要扩充运算,用于将两个关系根据特定条件合并。

θ\theta-连接

θ\theta-运算

  • 定义:

    RAθBS={(tr,ts)trRtsStr[A]θts[B]}R \mathop{\Join}\limits_{A \mathop{\theta} B} S = \{(t_r, t_s) \mid t_r \in R \land t_s \in S \land t_r[A] \mathop{\theta} t_s[B]\}

  • 操作符 RFSR \mathop{\Join}\limits_F S:(R product S) where F
  • 特点:
    • 从笛卡尔积中选取满足特定条件的元组
    • θ\theta 可使用各种比较运算符(=,<,>=, <, > 等)
等值连接

等值连接

  • 定义:当 θ\theta== 时的连接称为等值连接

    RA=BS={(tr,ts)trRtsStr[A]=ts[B]}R \mathop{\Join}\limits_{A=B} S = \{(t_r, t_s) \mid t_r \in R \land t_s \in S \land t_r[A] = t_s[B]\}

  • 特点:保留重复列

假设我们有两个表:

  • 学生表(Student):记录学生的学号和姓名。
学号 姓名
1 小明
2 小红
3 小刚
  • 选课表(CourseSelection):记录学生选课的情况,包括学号和课程。
学号 课程
1 数学
1 英语
2 数学
4 物理

示例:找出学生及其选课情况。

1
2
3
4
SELECT *
FROM Student S
JOIN CourseSelection C
ON S.学号 = C.学号;

结果:

学号_S 姓名 学号_C 课程
1 小明 1 数学
1 小明 1 英语
2 小红 2 数学

解释:

  • 条件是 S.学号 = C.学号,所以只有学号相同的记录会被保留。
  • 结果中仍然包含重复列(如 学号_S学号_C)。
自然连接

自然连接

  • 定义:特殊的等值连接,基于同名属性进行连接并去除重复列

    RS=πdistinct attr.(σcommon attr. equality(R×S))R \mathop{\Join} S = \pi_{\text{distinct attr.}}(\sigma_{\text{common attr. equality}}(R \times S))

  • 操作符:R join S
  • 特点:
    • 同时从行和列的角度进行运算
    • 结果关系模式为两个关系属性的并集

承接上面的示例:找出学生及其选课情况。

1
2
3
SELECT *
FROM Student S
NATURAL JOIN CourseSelection C;

结果:

学号 姓名 课程
1 小明 数学
1 小明 英语
2 小红 数学

解释:

  • 自然连接会自动找到两个表中同名的列(这里是「学号」),并基于这些列进行等值连接。
  • 结果中去掉了重复列(只有一个「学号」列)。
外连接
  • 悬浮元组:在自然连接中被舍弃的不匹配元组
  • 类型
    • 左外连接(⟕):保留左侧关系的悬浮元组
      • 操作符:R left outer join S
    • 右外连接(⟖):保留右侧关系的悬浮元组
      • 操作符:R right outer join S
    • 完全外连接(⟗):同时保留两侧的悬浮元组
      • 操作符:R full outer join S

示例:找出所有学生及其选课情况(如果没有选课,则显示 NULL)。

1
2
3
4
SELECT *
FROM Student S
LEFT JOIN CourseSelection C
ON S.学号 = C.学号;

结果:

学号_S 姓名 学号_C 课程
1 小明 1 数学
1 小明 1 英语
2 小红 2 数学
3 小刚 NULL NULL

解释:

  • 左侧表(Student)中的所有记录都被保留。
  • 如果某个学生没有选课(如小刚),则右侧表的字段显示为 NULL。

同理,右外连接和完全外连接的 SQL 语句与结果如下:

1
2
3
4
SELECT *
FROM Student S
RIGHT JOIN CourseSelection C
ON S.学号 = C.学号;
学号_S 姓名 学号_C 课程
1 小明 1 数学
1 小明 1 英语
2 小红 2 数学
NULL NULL 4 物理
1
2
3
4
SELECT *
FROM Student S
FULL JOIN CourseSelection C
ON S.学号 = C.学号;
学号_S 姓名 学号_C 课程
1 小明 1 数学
1 小明 1 英语
2 小红 2 数学
3 小刚 NULL NULL
NULL NULL 4 物理

除运算

除运算是关系代数中用于处理「全部」类查询的重要运算。除运算的作用是从一个表中找出那些满足另一个表中「所有条件」的记录。

  • 定义:

    R÷S={tr[A]trRπY(S)Yx}R \div S = \{t_r[A] \mid t_r \in R \land \pi_Y(S) \subseteq Y_x\}

    其中 YxY_xxxRR 中的象集
  • 操作符:R divideby S
  • 推导公式:

    R÷S=πX(R)πX((πX(R)×S)R)R \div S = \pi_{X}(R) - \pi_{X}((\pi_{X}(R) \times S) - R)

推导步骤:

  1. 计算最大可能结果集 Tmax=πX(R)T_{\max} = \pi_X(R)
  2. 计算 Rmax=Tmax×SR_{\max} = T_{\max} \times S
  3. 找出不符合条件的元组 T1=RmaxRT_1 = R_{\max} - R
  4. 投影得到不符合条件的 XX 值集合 T2=πX(T1)T_2 = \pi_X(T_1)
  5. 最终结果 R÷S=TmaxT2R \div S = T_{\max} - T_2

假设我们有两个表:

  • 学生选课表:
学号 课程
1 数学
1 英语
1 物理
2 数学
2 英语
3 数学
  • 课程表:
课程
数学
英语
物理

如果我们想找出选修了所有课程的学生,可以用除运算:

1
2
3
4
5
6
7
8
9
SELECT 学号
FROM 选课表
GROUP BY 学号
HAVING COUNT(DISTINCT 课程) = (SELECT COUNT(*) FROM 课程表);
-- DISTINCT 用于「去重」,若某个学生选修了重复的课程,只计算一次
-- COUNT(DISTINCT 课程) 计算每个学生选修的不同课程数量
-- COUNT(*) 计算课程表中的课程数量
-- HAVING 是 GROUP BY 的过滤条件,只保留满足条件的学生学号
-- 条件是选修的课程数量等于课程表中的课程数量,即选修了所有课程

结果:

学号
1

计算过程:

  1. 计算最大可能结果集 TmaxT_{\max},即所有可能的学生的学号
    学号
    1
    2
    3
  2. 使用笛卡尔积将学生与所有课程组结合起来,得到理想状态的选课表
    学号 课程
    1 数学
    1 英语
    1 物理
    2 数学
    2 英语
    2 物理
    3 数学
    3 英语
    3 物理
  3. 从理想选课表剔除实际选课表,得到不符合条件的学生
    学号 课程
    2 物理
    3 英语
    3 物理
  4. 投影得到不符合条件的学生学号
    学号
    2
    3
  5. 最终结果为 TmaxT_{\max} 减去不符合条件的学生学号
    学号
    1