关系数据库

mindmap
  root((关系数据库))
    关系数据结构及形式化定义
      域 Domain
      笛卡尔积
      关系 Relation
        基本关系/基表
        查询表
        视图表
    码的分类与作用
      候选码 Candidate Key
      主码 Primary Key
      外码 Foreign Key
      全码 All-Key
    数据完整性约束
      实体完整性 Entity Integrity
      参照完整性 Referential Integrity
      用户定义完整性 User-Defined Integrity
    关系模式与关系实例
      关系模式 Relation Schema
      关系实例 Relation Instance
    关系操作
      查询
      更新
    关系代数
      概述
      基本运算体系
        集合运算
          并运算 Union
          差运算 Difference
          笛卡尔积 Cartesian Product
        专门关系运算
          选择 Selection
          投影 Projection
      记号系统与核心概念
        元组连接
        象集
        关系模式语义

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

关系模型理论 关系数据库管理系统(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):外码要么为空,要么必须引用被参照关系中已存在的主码值。
  3. 用户定义完整性(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