数据库复习笔记 二.关系数据库
关系数据库系统是支持关系模型的数据库系统.
关系模型的三要素:
- 关系数据结构: 就是一张表
- 关系操作: 对表的操作, 选择, 投影, 连接, 除, 并, 交, 差等查询以及增, 删, 改
- 完整性约束: 实体完整性, 参照完整性, 自定义完整性
域: 取值范围, 域的基数: 可取值的数量
笛卡尔乘积: A 里的所有人和 B 里的所有人配对一次
关系: 笛卡尔积的一个子集, 从里面挑出有意义的内容
关系数据库: 关系是表, 关系数据库是装表的文件夹
关系模式: R (U,D,DOM,F)
- R: Relation Name, 表名
- U: 属性名的集合, 表有哪些列, 我也不知道为什么叫 U
- D: Domains, 域
- DOM: 属性到域的映射, 哪一列对应哪种类型
- F: 属性组间的依赖关系
完整性约束#
域完整性: 列的数据有效
实体完整性: 主键非空且唯一
参照完整性: 外键要么是空的, 要么对应存在的数据
自定义完整性: 「这是根据业务瞎定的规矩. 」 -- Gemini 3 Pro
关系代数#
并#
合并 S 和 R, 重复的只算一次.
交#
S 和 R 共有的部分.
并交#
病娇是二次元文化中的一种角色类型, 指对爱慕对象抱有极端占有欲, 表面甜蜜但内心疯狂, 常为「守护爱情」而做出伤害他人或所爱之人的危险行为的虚构形象.
差#
S - R: 在 S 但不在 R 的部分.
笛卡尔积#
行数 = S 的行数 × R 的行数
列数 = S 的列数 + R 的列数
R
| CNo | CN |
|---|---|
| C-11 | OS |
| C-21 | DB |
S
| SNo | SN | Age |
|---|---|---|
| S-01 | Huang | 21 |
| S-21 | Lin | 20 |
| S-30 | Shao | 22 |
R × S
| CNo | CN | SNo | SN | Age |
|---|---|---|---|---|
| C-11 | OS | S-01 | Huang | 21 |
| C-11 | OS | S-21 | Lin | 20 |
| C-11 | OS | S-30 | Shao | 22 |
| C-21 | DB | S-01 | Huang | 21 |
| C-21 | DB | S-21 | Lin | 20 |
| C-21 | DB | S-30 | Shao | 22 |
选择#
在关系 中选择满足条件 的元组 (行).
选出年龄大于 20 岁的学生:
| Sname | Age | Score |
|---|---|---|
| 张三 | 21 | 90 |
| 李四 | 22 | 50 |
| 范进 | 57 | 666 |
投影#
从关系 中选出若干属性列 , 并自动去除重复行. 注意去除的是行不是列.
说人话就是竖切, 只保留想要的列.
查询学生的姓名和年龄:
| Sname | Score |
|---|---|
| 张三 | 90 |
| 李四 | 50 |
| 王五 | 88 |
| 范进 | 666 |
连接#
将两个关系 和 按条件拼在一起.
本质是在 S 和 R 中选取属性满足一定条件的元组, 拼在一起得到一张新的表.
R (学生表): 列有 [学号, 姓名, 班级号]
S (班级表): 列有 [班级号, 班级名]
等值连接#
筛选条件为相等.
在 R 和 S 中挑选 R.班级号 = S.班级号的行, 拼在一起, 不删除重复列, 于是结果里会有两列班级号.
自然连接#
两个关系有同名属性, 在同名属性上做等值连接, 删掉重复列.
虽然等值连接和自然连接的筛选条件都是相等, 但连接的筛选条件可以不是相等, 例如筛选出所有 R 中学号 > S 中班级号的项拼成一张表:
结果类似:
| 学号 | 姓名 | R.班级号 | S.班级号 | 班级名 |
|---|---|---|---|---|
| 205 | 李四 | 102 | 101 | 计算机 1 班 |
| 205 | 李四 | 102 | 102 | 计算机 2 班 |
| 205 | 李四 | 102 | 103 | 计算机 3 班 |
外连接#
普通的连接 (内连接): 如果张三没分班级, 或者这个班级没人, 连接的时候这些数据就会被丢弃.
左外连接: 保留左边的表的全部数据, 空白的地方填 NULL.
右外连接, 全外连接同理.
除法#
R (应聘者技能表)
| 姓名 | 技能 |
|---|---|
| 张三 | Java |
| 张三 | Python |
| 李四 | Java |
| 王五 | Python |
| 张三 | C++ |
S (录取要求表)
| 技能要求 |
|---|
| Java |
| Python |
R ÷ S : 找到 R 中包含 S 所有项的对应项
| 姓名 |
|---|
| 张三 |
注意 R 和 S 中对应项可以不同名, 但需要有相同的域.
R (供应商供应零件)
| 供应商 | 零件 | 项目 |
|---|---|---|
| S1 | P1 | J1 |
| S1 | P2 | J2 |
| S2 | P1 | J1 |
| S2 | P2 | J1 |
| S2 | P1 | J2 |
| S3 | P2 | J2 |
S (需求的零件和项目)
| 零件 | 项目 |
|---|---|
| P1 | J1 |
| P2 | J2 |
R ÷ S:
- S1: 有 (P1, J1) 和 (P2, J2), 覆盖 S
- S2: 缺 (P2, J2)
- S3: 缺 (P1, J1)
结果:
| 供应商 |
|---|
| S1 |
外部并#
普通的并要求两个关系的列数和类型相同, 外部并就是硬凑在一起.
关系 A
| 姓名 | QQ 号 |
|---|---|
| 哈基米 | 23333 |
关系 V
| 姓名 | 微信号 |
|---|---|
| 胖宝宝 | hachimi |
外部并 A ∪ V:
| 姓名 | QQ 号 | 微信号 |
|---|---|---|
| 哈基米 | 23333 | NULL |
| 胖宝宝 | NULL | hachimi |
为什么这里把 S 和 R 换成 A 和 V 了呢, 因为我觉得 A∪V 看起来很像 AUV.
半连接#
R 和 S 的半连接定义为 R 和 S 的自然连接在关系 R 的属性集上的投影.
人话: 只要 R 中在 S 出现过的数据, 不加入 S 中的数据, 只用来匹配.
表 R (北京员工表):
| 工号 | 姓名 | 部门 |
|---|---|---|
| 001 | 老王 | 销售 |
| 002 | 小李 | 技术 |
| 003 | 大刘 | 销售 |
表 S (上海出差记录表):
| 工号 | 地点 |
|---|---|
| 001 | 南京 |
| 003 | 杭州 |
| 005 | 苏州 |
半连接 R ⋉ S:
| 工号 | 姓名 | 部门 |
|---|---|---|
| 001 | 老王 | 销售 |
| 003 | 大刘 | 销售 |
太好了, 我逐渐理解一切.
关系代数应用举例#
S (S#,SN,SSEX,SAGE)
C (C#,CN,TEACHER)
SC (S#,C#,GRADE)
其中 # 代表学号, N 代表名字.


关系代数的等价规则#
连接和笛卡尔积满足交换律和结合律.

投影和选择满足串接定律, 其实是废话.
选择和投影满足交换律, 前提是筛选条件 F 里用到的列包含在投影名单 A 里.

选择对笛卡尔积, 并, 差满足分配率.



利用规则优化查询#
语法树优化:
https://www.bilibili.com/video/BV1Fp4y1a7Cs/
先选择再投影.