数据库原理与应用
第一章 绪论
1.1 数据库系统概述
1.1.1 4个基本概念
- 数据 Data
- 数据库 Database
- 数据库管理系统 DBMS
- 数据库系统 DBS
1.1.2 数据管理技术的产生与发展
- 人工管理阶段
- 文件系统阶段
- 数据库系统阶段
1.2 数据模型
1.2.1 两类数据模型
- 概念模型
- 逻辑模型和物理模型
1.3 数据库系统的结构
从数据库最终用户角度看,数据库系统结构分为
- 单用户结构
- 主从式结构
- 分布式结构
- 客户-服务器 C/S
- 浏览器-应用服务器 B/S
1.3.2 数据库系统的三级模式结构
- 模式 Schema
- 外模式 External Schema
- 内模式 Internal Schma
1.4 数据库系统的组成
第二章 关系数据库
2.1 关系数据结构及形式化定义
2.1.1 关系
- 单一的数据结构 —— 关系
-
逻辑结构 —— 二维表
从用户角度,关系模型中数据的逻辑结构是一张二维表
-
建立在几何代数的基础上
1. 域 Domain
一组具有相同数据类型的值的集合
2. 笛卡尔积
给定一组域D1, D2, ..., Dn,允许其中某些域时相同的。
D1, D2, ..., Dn的笛卡尔积为:
-
元组
笛卡尔积中的每一个元素(d1, d2, ..., dn)叫做一个 n 元组
3. 关系 Relation
(1) 关系
\(D_1\times D_2 \times ... \times D_n\)的子集叫做在域 D1, D2, ..., Dn 上的关系,表示为
(4) 关系的表示
关系也是一个二维表,表的每行对应一个元组,每列对应一个域
(5) 属性
-
关系中不同列可以对应相同的域
-
为了加一区分,必须对每列起一个名字,称为属性(Attribute)
-
n 目关系必有 n 个属性
(6) 码
-
候选码 Candidate key
若关系中的某一属性组的值能唯一地标识一个元组,则称该属性组为候选码
简单的情况:候选码质保函一个属性
-
全码 All-key
最极端的情况:关系模式的所有属性组是这个关系模式的候选码,称为全码(All-key)
(7) 三类关系
-
基本关系
实际存在的表
-
查询表
查询结果对应的表
-
视图表
由基本表或其他视图表导出的表,是虚表,不对应实际存储的数据
2.1.2 关系模式
1. 什么是关系模式
-
关系模式(Relation Schema)是型
-
关系是值
-
关系模式是对关系的描述
-
元组集合的结构
- 属性构成
- 属性来自的域
- 属性与域之间的映象关系
-
完整性约束条件
-
2. 定义关系模式
关系模式可以形式化的表示为:
- R 关系名
- U 组成该关系的属性名集合
- D U 中属性所来自的域
- DOM 属性象域的映像集合
- F 属性间数据的依赖关系的集合
2.1.3 关系数据库
2.2 关系操作
2.2.1 基本的关系操作
-
常用的关系操作
-
查询操作:选择、投影、连接、除、并、差、交、笛卡尔积
-
数据更新:插入、删除、修改
-
-
关系操作的特点
都是集合操作方式:操作的对象和结果都是集合
2.2.2 关系数据库语言的分类
-
关系代数语言
- 用对关系的运算来表达查询要求
- 代表:ISBL
-
关系演算语言:用谓词来表达查询要求
- 元组关系演算语言
- 域关系演算语言
-
具有关系代数和关系演算双重特点的语言
- 代表:SQL(Structured Query Language)
2.3 关系的完整性
就是表的约束规则,有三类完整性约束:
E A R
2.3.1 实体完整性
- 若属性 A 是基本关系 R 的主属性,则属性 A 不能取空值
2.3.2 参照完整性
1. 关系间的引用
- 在关系模型中实体及实体键的联系都是用关系来描述的,自然存在着关系与关系间的引用
例2.1 学生实体、专业实体
学生(学号,姓名,性别,专业号,年龄)
专业(专业号,专业名)
- 学生关系引用了专业关系的主码“专业号”
- 学生关系中的“专业号”值必须是确实存在的专业的专业号
外码连的是另一个表的主码
例2.3 学生实体及其内部的一对多联系
学生(学号,姓名,性别,专业号,年龄,班长)
-
学号是主码,班长是外码,引用了本关系的学号
-
班长必须是确实存在的学生的学号
2. 外码(Foreign Key)
-
设 F 是基本关系 R 的一个或一组属性,但不是关系 R 的码
如果 F 与基本关系 S 的主码 Ks 相对应,则称 F 是 R 的外码
-
基本关系 R 称为参照关系(Referencing Relation)
-
基本关系 S 称为被参照关系(Referenced Relation) 或目标关系(Target Relation)
-
关系 R 和 S 可以是同一个关系
-
目标关系 S 的主码 Ks 和参照关系的外码 F 必须定义在同一个(或一组)域上
-
外码不一定要与相应的主码同名(有时候相同含义但名字不完全相同)
3. 参照完整性规则
数据库中,引用必须有效✍️✍️✍️
外码是引用别人的主码的
所以外码要么就是空值,要么一定能在别人的主码里找到
2.3.3 用户定义的完整性
就是自己定义的规则,例如“课程号”属性必须取唯一值,“课程名”属性不能为空。。。
2.4 关系代数
关系代数运算符:
集合运算符
| 运算符 | 含义 |
|---|---|
| \(\cup\) | 并 |
| \(-\) | 差 |
| \(\cap\) | 交 |
| \(\times\) | 笛卡尔积 |
专门的关系运算符
| 运算符 | 含义 |
|---|---|
| \(\sigma\) | 选择 |
| \(\pi\) | 投影 |
| \(\bowtie\) | 连接 |
| \(\div\) | 除 |
2.4.1 传统的集合运算
(1) 并 Union
-
R 和 S
- 具有相同的目 n(既两个关心都有 n 个属性)
- 相应的属性取自同一个域
-
\(R \cup S\)
- 仍为 n 目关系,由属于 R 或属于 S 的元组组成
(2) 差 Difference
-
R 和 S
- 具有相同的目 n(既两个关心都有 n 个属性)
- 相应的属性取自同一个域
-
\(R - S\)
- 仍为 n 目关系,由属于 R 而不属于 S 的元组组成
(3) 交 Intersection
-
R 和 S
- 具有相同的目 n(既两个关心都有 n 个属性)
- 相应的属性取自同一个域
-
\(R \cap S\)
- 仍为 n 目关系,由既属于 R 又属于 S 的元组组成
(4) 笛卡尔积 Cartesian Product
- 是广义的笛卡尔积(Extended Cartesian Product)
- R: n 目关系,k1 个元组
- S: m 目关系,k2 个元组
-
\(R \times S\)
-
列:(n + m) 列元组的集合
- 元组的前 n 列是关系 R 的一个元组
- 后 m 列是关系 S 的一个元组
-
行:\(k_1 \times k_2\)个元组
-
2.4.2 专门的关系运算
先引入几个记号
(1) \(R, t \in R, t[A_i]\)
设关系模式为 \(R(A_1, A_2, ..., A_n)\)
他的一个关系设为 R
\(t \in R\) 表示 \(t\) 是 \(R\) 的一个元组 (tuple)
\(t[A]\) 则表示 元组 \(t\) 中相应于属性 \(A_i\) 的一个分量
(2) \(A, t[A], \bar{A}\)
若 \(A = \{A_{i1}, A_{i2}, ..., A_{ik}\}\),其中 \(A_{i1}, A_{i2}, ..., A_{ik}\)是 \(A_1, A_2, ..., A_n\)中的一部分,则\(A\)称为属性列或属性组。
\(t[A] = (t[A_{i1}], t[A_{i2}], ..., t[A_{ik}])\) 表示元组 \(t\)在属性列 \(A\)上诸分量的集合。
(3) \(\overset{\frown}{t_r t_s}\)
\(R\) 为 \(n\) 目关系,\(S\) 为 \(m\) 目关系。 \(t_r \in R, t_s \in S, \overset{\frown}{t_r t_s}\) 称为元组的连接
\(\overset{\frown}{t_r t_s}\) 是一个 \(n + m\) 列的元组,前 \(n\) 个分量为 \(R\) 中的一个 \(n\) 元组,后 \(m\) 个分量为 \(S\) 中的一个 \(m\) 元组
(4) 象集 \(Z_x\)
给定一个关系 \(R(X, Z)\),\(X\) 和 \(Z\) 为属性组。
当 \(t[X] = x\)时,\(x\) 在 \(R\) 中的象集(Images Set) 为:
他表示 \(R\) 中属性组 \(X\) 上值为 \(x\) 的诸元组在 \(Z\) 上分量的集合
例
R
| x1 | Z1 |
|---|---|
| x1 | Z2 |
| x1 | Z3 |
| x2 | Z2 |
| x2 | Z3 |
| x3 | Z1 |
| x3 | Z3 |
- x1 在 R 中的象集
- x2 在 R 中的象集
- x3 在 R 中的象集
Info
象集,是根据一个元组,由原先的关系中计算得到的一组元组的集合
其中依据的元组是从原先的关系中抽取出来的,附带有原先关系中的属性
尽管是元组的集合,我们不把象集叫做关系,因为我们不关注象集的属性,只关注象集内的值
1. 选择 Selection
SELECT
从关系 R 中选取满足条件的元组
- 选择又称为限制 Restriction
-
选择运算符的含义
- 在关系 R 中选择满足给定条件的诸元组
\[\sigma_F(R) = {t \mid t \in R \land F(t) = True}\]-
\(F\): 选择条件,是一个逻辑表达式,取值为 True or False
- 基本形式为:\(X_1 \theta Y_1\)
- \(\theta\) 表示比较运算符,可以是\(<,>,<=,>=,=,<>\)
例2.4 查询信息系(IS系)全体学生
2. 投影 Projection
- 从 R 中选择出若干熟悉列组成新的关系
Projection
投影是从关系中挑选一些列
投影之后不仅取消了原关系中的某些列,而且还可能取消某些元组(避免重复行)
3. 连接 Join
连接也称 \(\theta\) 连接
从两个关系的笛卡尔积中选取属性减满足一定条件的元组
- \(A 和 B: 分别为R 和 S 上度数相等且可比的属性组\)
- \(\theta\): 比较运算符
连接 Join
连接运算从 R 和 S 的广义笛卡尔积 \(R \times S\)中选取\(R\)关系在\(A\)属性列上的值与\(B\)属性组上的值满足比较关系\(\theta\)的元组
连接操作是从行的角度进行运算
自然连接还需要取消重复列,所以是同时从行和列的角度进行运算
- 两类常用的连接运算
等值连接
-
\(\theta\)为\(=\)的连接运算称为等值连接
-
从关系\(R与S\)的笛卡尔积中选取\(A、B\)属性值相等的那些元组,即:
自然连接 Natural join
-
自然连接是一种个特殊的等值连接
- 两个关系中进行比较多分量必须是相同的属性组
- 在结果中把重复的属性列去掉
-
自然连接的含义
R和S具有相同的属性组 B
\[R \bowtie S = \{\overset{\frown}{t_r t_s} [U-B] \mid t_r \in R \land t_s \in S \land t_r[B] = t_s[B]\}\]
写法上就是连接 \(\bowtie\) 运算符不用加下标了
-
悬浮元组 Dangling tuple
- 两个关系在做自然连接时,关系 R 中某些元组有可能在 S 中不存在公共属性上值相等的元组,从而造成 R 中这些元组在操作时被舍弃了,这些被舍弃的元组称为悬浮元组
-
外连接 Outer Join
-
如果把悬浮元组也保存在结果关系中,而在其他属性上填空值Null,就叫做外连接
-
左外连接 Left Outer Join
- 只保留左边关系 R 中的悬浮元组
-
右外连接
- 只保留右边关系 S 中的悬浮元组
-
例2.8 关系 R 和关系 S 如下所示:
- R
| A | B | C |
|---|---|---|
| a1 | b1 | 5 |
| a1 | b2 | 6 |
| a2 | b3 | 8 |
| a2 | b4 | 12 |
- S
| B | E |
|---|---|
| b1 | 3 |
| b2 | 7 |
| b5 | 10 |
| b3 | 2 |
| b2 | 2 |
- 外连接
| A | B | C | E |
|---|---|---|---|
| a1 | b1 | 5 | 3 |
| a1 | b2 | 6 | 7 |
| a1 | b2 | 8 | 2 |
| a2 | b3 | 8 | 2 |
| a2 | b4 | 12 | NULL |
| NULL | b5 | NULL | 10 |
- 左外连接
保留 R 中所有行
| A | B | C | E |
|---|---|---|---|
| a1 | b1 | 5 | 3 |
| a1 | b2 | 6 | 7 |
| a1 | b2 | 6 | 2 |
| a2 | b3 | 8 | 2 |
| a2 | b4 | 12 | NULL |
4. 除运算 Division
给定关系 \(R(X, Y)\) 和 \(S(Y, Z)\),其中 \(X, Y, Z\) 为属性组
\(R\) 中的 \(Y\) 与 \(S\) 中的 \(Y\) 可以有不同的属性名,但必须出自相同的域集
\(R\) 与 \(S\) 的除运算得到一个新的关系 \(P(X)\)
\(P\) 是 \(R\) 中满足下列条件的元组在 \(X\) 属性列上的投影:
元组在 \(X\) 上分量值 \(x\) 的象集 \(Y_x\)包含\(S\) 在 \(Y\) 上投影的集合
除操作是同时从行和列角度进行运算

对于 \(S\) 的计算很简单,只要从 \(S\) 中提取 \(Y\) 属性的所有元组,即 \(\Pi_Y (S)\)
然后找 \(R[X]\) ( \(t_r \in R, t_r[X]\) ) 中哪些元组的象集包含住了 \(\Pi_Y (S)\)
求的就是满足这个条件的 \(t_r\) 的集合组成的新关系
例2.9
R
| A | B | C |
|---|---|---|
| a1 | b1 | c2 |
| a2 | b3 | c7 |
| a3 | b4 | c6 |
| a1 | b2 | c3 |
| a4 | b6 | c6 |
| a2 | b2 | c3 |
| a1 | b2 | c1 |
S
| B | C | D |
|---|---|---|
| b1 | c2 | d1 |
| b2 | c1 | d1 |
| b2 | c3 | d2 |
\(R \div S:\)
| A |
|---|
| a1 |
R 和 S 共有的列:B, C
\(\Pi_{B, C} = \{ \{b1, c2 \}, \{b2, c1 \}, \{ b2, c3 \} \}\)
\(R[A]\) 中的元组中的象集包含了 \(\Pi_{B, C}\) 的只有 a1
例2.10 查询至少选修1号课程和3号课程的学生号码
寻找:选课序号中包含 1, 3,即求:
建立临时关系 K: Cno{1, 3}
然后有4道习题
跳转链接【数据库第2章 关系数据库 (下)】 【精准空降到 1:08:13】
2.5 *关系演算
第三章 关系数据库标准语言 SQL
3、4、5 就是 SQL 基础
3.1 SQL 概述
Structured Query Language
布拉布拉有一堆概念
3.1.2 SQL 的特点
-
综合统一
- 集 DDL, DML, DCL 于一体
- 。。。
-
高度非过程化
只要关注要做什么,不用关心怎么做的
-
面向集合的操作方式
-
以同一种语法结构提供多种使用方式
既是独立的语言,有是嵌入式语言(能够嵌入高级语言?)
-
语言简洁,易学易用
完成核心功能只用了9个动词:

3.2 学生-课程数据库
我们的课本的数据库实例要比这个复杂地多,那个b袁神说要背下来,还没怎么看
这里的这个数据库是这样的:
-
学生-课程模式 S-T:
学生表:Student(Sno, Sname, Ssex, Sage, Sdept)
课程表:Course(Cno, Cname, Cpno, Ccredit)
学生选课表:SC(Sno, Cno, Grade)
3.3 数据定义
定义分为:
- 模式定义
- 表定义
- 视图和索引的定义

sql 中的关键字不区分大小写
3.3.1 模式的定义与删除
1. 定义模式
例3.2 create schema authorization WANG;
该语句没有指定<模式名>,<模式名>隐含为<用户名>
- 定义模式实际上定义了一个命名空间
-
在空间中可以定义该模式包含的数据库对象
例如基本表、视图、索引
-
在
create schema中可以接受create table,create view和grant子句
例3.3 为用户 ZHANG 创建一个模式 TEST,并在其中定义一个表 TAB1
sql 中的数据类型也不区分大小写
2. 删除模式
-
cascade 级联
删除模式的同时把该模式中所有的数据库对象全部删除
-
restrict 限制
如果该模式中定义了下属的数据库对象(表、视图等),则拒绝删除
没有时可以执行删除
3.3.2 基本表的定义、删除与修改
1. 定义基本表
- <表名>:所要定义的基本表的名字
- <列名>:组成给表的各个属性(列)
- <列级完整性约束条件>:涉及相应属性列的完整性约束条件
- <表级完整性约束条件>:涉及一个或多个属性列的完整性约束条件
推荐写法
例3.5 建立学生表Student,学号是主码,姓名取值唯一
例3.7 建立一个学生选课表SC
2. 数据类型

常见数据类型表格
3. 模式与表
- 每个基本表都属于一个模式
- 一个模式包含多个基本表
-
定义基本表所属模式(关注前两个方法就行)
- 方法一:在表名中明显地给出模式名
-
方法二:在创建模式语句中同时创建表
在模式定义里有讲
-
方法三:设置所属的模式
4. 修改基本表
alter table <表名>
[add [column] <新列名><数据类型>[完整性约束]]
[add <表级完整性约束>]
[drop [column] <列名> [cascade|restrict]]
[drop constraint <完整性约束名> [restrict|cascade]]
[alter column <列名><数据类型>];
5. 删除基本表
-
restrict
删除有限制,例如当基本表上建有视图时
-
cascade
删除时全部删光!没有限制
3.3.3 索引的建立与删除
- 建立索引的目的:加快查询速度
-
关系数据库管理系统中常见索引:
- 顺序文件上的索引
- B+ 树索引
- 散列(hash)索引
- 位图索引
-
特点:
- B+树索引具有动态平衡的优点
- hash索引具有查找速度快的特点
-
谁可以建立索引?
数据库管理员或表的属主可以建立索引
-
谁维护索引?
关系数据库管理系统自动完成
-
怎么选择使用哪种索引?
关系数据库管理系统自动选择合适的所有作为存取路径,用户不必也不能显示地选择索引
1. 建立索引
- <次序>:指定索引值的排列次序- 升序:ASC
- 降序:DESC
- 缺省:默认ASC
- unique:此索引的每一个索引值只对应唯一的数据记录
- cluster:表示要建立的索引是聚簇索引(类似按首字母分好类就是聚簇索引)
Tip
unique:建表时限制数据不能重复
distinct:查询数据时去重
例3.13 为学生-课程数据库中的Student, Course, Sc三个表建立索引。Student表按学号升序建立唯一索引,Course表按课程号升序建唯一所有,SC表按学号升序和课程号降序建唯一索引
2. 修改索引
3. 删除索引
3.3.4 数据字典
不重要
3.4 数据查询
select [all|distinct] <目标列表达式>[,<目标列表达式>]...
from <表名或视图名>[,<表名或视图名>]...|(select语句)
[as]<别名>
[where <条件表达式>]
[group by <列名1> [having <条件表达式>]]
[order by <列名2> [asc|desc]];
-
select 子句
指定要显示的属性列
-
from 子句
指定查询对象
-
where 子句
指定查询条件
-
group by 子句:
对查询结果按指定列的值分组,该属性列值相等的元组为一个组。通常会在每组中作用聚集函数
-
having 短语
只有满足指定条件的组才予以输出
-
order by 子句
对查询结果表按指定列值的升序或降序排序
Tip
1 单表查询章节就是把这几个子句讲清楚
2-4 连接查询、嵌套查询、集合查询通常涉及到多个表
同一个题可能可以用这三种方法有不同的做法
3.4.1 单表查询
查询只涉及一个表
输入输出分析法
输入:from子句
输出:select子句
分析:where子句
3.4.1.1 选择表中的若干列
查询全部列
选出所有属性列:
- 在 select 关键字后面列出所有列名
- 将<目标列表达式>指定为*
查询经过计算的值
select子句的<目标表达式>不仅可以为表中的属性列,也可以是表达式
使用列别名改变查询结果的列标题
select Sname NAME, 'Year of Birth:' BIRTH,
2026 - Sage BIRTHDAY, LOWER(Sdebt) DEPARTMENT
from Student;
可以用()确定优先级(例如减法表达式),不过一般sql都能把表达式正常解析
3.4.1.2 选择表中若干元组
消除取值重复的行
如果没有指定 distinct 关键字,则缺省为 all
查询满足条件的元组
1.比较大小

2.确定范围
谓词:between... and..., not between... and...
例3.25 查询年龄在20-23岁之间的学生的姓名、系别和年龄
例3.26 查询年龄不在20-23之间的学生姓名、系别和年龄
3.确定集合
谓词:in <值表>, not in <值表>
例3.27 查询计算机科学系(CS)、数学系(MA)和信息系(IS)学生的姓名和性别
例3.28 查询既不是计算机科学系、数学系,也不是信息系的学生的姓名和性别
4.字符匹配
谓词:[not] like '<匹配串>' [escape '<换码字符>']
<匹配串>可以是一个完整的字符串,也可以含有通配符%和_
- %代表任意长度(长度可以为0)的字符串
- _代表任意单个字符
Tip
字符匹配,主要是提供了类似正则表达式的通配符规则
- 使用换码字符将通配符转义为普通字符
- pattern:匹配模式。
- escape_character:指定的转义字符,用于标记通配符为普通字符。
例3.34 查询DB_Design课程的课程号和学分
5.涉及空值的查询
谓词:is null或is not null
is 不能用等于号代替
例3.36 某些学生选修课程后没有参加考试,所以有选课记录,但没有开始成绩,查询缺少成绩的学生的学号和相应的课程号
6.多重条件查询
逻辑运算符:and和or来连接多个查询条件
- and的优先级高于or
- 可以用括号改变优先级
3.4.1.3 order by 子句
-
order by子句
- 可以按一个或多个属性列排序
- 升序:ASC;降序:DESC;缺省为升序
-
对于空值,排序时显示的次序由具体系统实现来决定,空值跟大头
order by 子句作用就是控制显示的时候以升序或降序形式排列
例3.39 查询选修了3号课程的学生的学号及其成绩,查询结果按分数降序排列
3.4.1.4 聚集函数 aggregate function
Warning
聚集函数只能出现在select语句和having子句中
count(*) # 统计元组个数
count([distinct|all] <列名>) # 计算一列中值的个数
sum([distinct|all] <列名>) # 计算一列值的总和(此列必须为数值型)
avg([distinct|all] <列名>) # 一列值的平均值(此列必须为数值型)
max([distinct|all] <列名>)
min([distinct|all] <列名>) # 求一列中的最大值和最小值
例3.45 查询学生201215012选修课程的总学分数
3.4.1.5 group by 子句
细化聚集函数的作用对象
- 如果未对查询结果分组,聚集函数将作用于整个查询结果
-
对查询结果分组后,聚集函数将分别作用于每个组
-
按指定的一列或多列值分组,值相等的为一组
group by的作用是控制聚集函数的作用范围
group by执行后,多行会被压缩成一组
SQL 有固定的逻辑执行顺序
所以group by执行过后,select后面只能写两类东西:
group by分组列本身- 聚集函数
也就是不可能出现非group by分组列的属性列
例3.47 查询选修了3门以上课程的学生学号
having 和 where 的区别
- 作用对象不同
- where 子句作用于基表或视图,从中选择满足条件的元组
- having短语作用域组,从中选择满足条件的组
Warning
单表查询中的 5 个基础子句讲完了,非常重要,接下来开始多表查询(连接、嵌套、集合)
3.4.2 连接查询
连接查询:同时涉及两个以上的表的查询
连接条件或连接谓词:用来连接两个表的条件
[<表名1>.]<列名1> <比较运算符> [<表名2>.]<列名2>-
[<表名1>.]<列名1> between [<表名2>.]<列名2> and [<表名2>.]<列名3> -
连接条件中的歌链接字段类型必须是可比的,但名字不必相同
3.4.2.1 等值与非等值连接查询
等值连接:连接运算符为=
连接操作的执行过程
-
嵌套循环法 nested-loop
遍历表一的每个元组,遍历表二的每个元组,判断两个元组是否满足连接条件,满足就加入结果表中
-
排序合并法 sort-merge
- 常用与=连接
- 首先按连接属性对表1和表2排序
- 遍历表一的每个元组,然后遍历表二的每个元组,由于单调性,找到第一个不满足的就停止遍历
-
索引连接 index-join
我们不需要关心这些具体的实现方法
自然连接
记得关系代数里讲连接 \(\bowtie\) 运算的时候讲到了自然连接,而在sql语言中自然连接的实现方式就是把所有的属性列名都写出来,手动去重
一条SQL语句可以同时完成选择和连接查询,这时where子句是由连接谓词和选择谓词组成的复合条件
3.4.2.2 自身连接
- 自身连接:一个表语自己连接
- 需要给表起别名以示区别
- 由于所有属性名都是同名属性,听次必须使用别名前缀
查询每一门课的间接先修课(即先修课的先修课)
3.4.2.3 外连接
外连接与普通连接的区别
- 普通连接操作只输出满足连接条件的元组
- 外连接操作以指定表为连接主体,将主体表中不满足连接条件的元组一并输出
-
左外连接
列出左边关系中所有的元组
-
右外连接
列出右边关系中所有的元组
Tip
外连接可以保留没有匹配上的行,把没匹配上的另一侧补成 NULL
左外连接就会把左表全部保留
例3.53 改写[例3.49]
3.4.2.4 多表连接
例3.54 查询每个学生的学号、姓名、选修的课程名及成绩
3.4.3 嵌套查询
连接查询 VS 嵌套查询
连接查询会有不可避免的笛卡尔积,开销大
- 一个select-from-where语句称为一个查询块
- 将一个查询块嵌套在另一个查询块的where子句或having短语的条件中的查询称为嵌套查询
相关子查询
子查询的查询条件依赖于父查询
-
首先取外层查询中表的第一个元组,根据它与内层查询相关的属性值处理内层查询,若where子句返回值为真,则取此元组放入结果表
-
然后再取外层表的下一个元组
-
重复这一过程,直至外层表全部检查完为止
查询每个学生中,成绩高于该学生平均成绩的选课记录
也是两层for循环的感觉
- 上层的查询块称为外层查询或父查询
- 下层查询块称为内层查询或子查询
-
SQL 语言允许多层嵌套查询
- 即一个子查询中还可以嵌套其他子查询
-
子查询的限制
- 不能使用 order by 子句
3.4.3.1 带有in谓词的子查询
例3.55 查询与刘晨在同一个系学习的学生
select Sno, Sname, Sdept
from Student
where Sdept in ( # 这里的in也可以写=,因为只有一个专业
select Sdept
from Student
where Sname = '刘晨'
);
也可以用连接查询做!
select S1.Sno, Sname, Sdept
from Student S1, Student S2
where S1.Sdept = S2.Sdept and
S2.Sname = '刘晨';
但是连接查询因为有笛卡尔积就会慢一点,但是现代数据库都会优化,所以不存在慢的说法了
3.4.3.2 带有比较运算符的子查询
例3.57 找出每个学生超过他选修课程平均成绩的课程号
Tip
相关子查询里,from后面的表起别名后,传入子查询中,就有了for循环的感觉
3.4.3.3 带有any(some)或all谓词的子查询
是一个把集合转换成值的函数
例3.58 查询非计算机科学系中比计算机科学系任意一个学生年龄小的学生姓名和年龄

3.4.3.4 带有exists谓词的子查询
例3.61 查询没有选修1号课程的学生姓名
exists 像是对于外部的一条元组写一个if语句,exists后面的内容基本上是和外面的一个子查询有关的,返回的是true or false,还有一种用法是exist里写select 1...where... 如果查询的表不为空就会返回1
3.4.4 集合查询
- 并操作 union
- 交操作 intersect
- 差操作 except
例3.64 查询计算机科学系的学生及年龄不大于19岁的学生
例3.68 查询计算机科学系的学生与年龄不大于19岁的学生的差集
连接、嵌套、集合就是一道题的3种做法
3.4.5 基于派生表的查询
子查询出现在 from 子句中
例3.57 找出每个学生超过他自己选修课程平时成绩的课程号
3.4.6 select语句的一般形式
select [all|distinct]
<目标列表达式> [别名] [,<目标列表达式> [别名]]...
from <表名或视图名> [别名]
[,<表名或视图名> [别名]]...
| (<select语句>) [as] <别名>
[where <条件表达式>]
[group by <列名1> [having <条件表达式>]]
[order by <列名2> [asc|desc]];
3.5 数据更新
3.5.1 插入数据
例3.69 将一个新学生元组(学号:201215128;姓名:陈冬;性别:男;所在系:IS;年龄:18岁)插入到Student表中
没有复制的属性列自动赋空值,但还是都显式写出来比较好
3.5.2 插入子查询的结果
- select子句目标列必须与into子句匹配
关系数据库管理系统在执行插入语句时会检查所插元组是否破坏表上已定义的完整性规则
- 实体完整性
- 参照完整性
-
用户完整性
- not null约束
- unique 约束
- 值域约束
3.5.2 修改数据
三种修改方式
- 修改某一个元组的值
- 修改多个元组的值
- 带子查询的修改语句
例3.75 将计算机科学系全体学生的成绩置零
-
关系数据库管理系统在执行修改语句时会检查所插元组是否破坏表上已定义的完整性规则
- 实体完整性
- 主码不允许修改
-
用户定义的完整性
- not null约束
- unique约束
- 值域约束
3.5.3 删除数据
三种删除方式(和修改一样)
- 删除某一个元组的值
- 删除多个元组的值
- 带子查询的删除语句
3.5.3.1 删除某一个元组的值
3.5.3.2 删除多个元组的值
3.5.3.3 带子查询的删除语句
3.6 空值的处理
3.6.1 空值的产生
没啥东西
3.6.2 空值的判断
is null is not null
3.6.3 空值的约束条件
属性定义中
- 有not null约束条件的不能取空值
- 加了unique限制的属性不能取空值
- 码属性不能取空值
3.7 视图
虚表
3.7.1 定义视图
视图定义语句里有建立和删除,但修改语句介绍的较少,因为与其修改不如删了重建一个
3.7.1.1 建立视图
- 基于多个基表的视图
例3.86 建立信息系选修了1号课程的学生的视图(包括学号、姓名、成绩)
-
基于视图的视图
-
带表达式的视图
-
分组视图
例3.90 将Student表中所有女生记录定义为一个视图
3.7.1.2 删除视图
默认是restrict
3.7.2 查询视图
查询视图和查询基本表的操作基本相同,视图就是个表
原理使用的是视图消解法(不关心)
3.7.3 更新视图
例3.95 将信息系学生视图IS_Student中学号“201215122”的学生姓名改为“刘辰”
Warning
- 允许对行列自己视图进行更新
- 对其他类型视图的更新不同系统有不同限制
3.7.4 视图的作用
略
第四章 数据库的安全性
-
数据库的安全性是指保护数据库以防止不合法使用所造成的数据泄漏、更改或破坏
-
系统安全保护措施是否有效是数据库系统主要性能指标之一
4.1 数据库安全性概述
4.1.1 数据库的不安全因素
- 黑客、非授权用户
- 重要敏感数据泄漏
- 安全环境脆弱性
4.1.2 安全标准简介
-
TCSEC
-
CC
4.2 数据库安全性控制(重点)
4.2.1 用户身份鉴别
4.2.2 存取控制
-
定义用户权限,并将用户权限登记到数据字典中
-
合法权限检查
组成了数据库管理系统的存取控制系统
常用存取控制方法:
-
自主存取控制(Discretionary Access Control, DAC)
C2 级
-
强制存取控制(Mandatory Access Control, MAC)
B1 级
4.2.3 自主存取控制方法
通过 SQL 的 GRANT 语句和 REVOKE 语句实现
4.2.4 授权:授予与回收
4.2.4.1 GRANT
例4 把查询 Student 表和修改学生学号的权限授给用户 U4
例5 把对表 SC 的 INSERT 权限授予 U5用户,并允许他再将此权限授予其他用户
2. REVOKE
授予的权限可以由数据库管理员或其他授权者用 REVOKE 语句收回CASCADE: 凡是从你这传出去的全给删了
RESTRICT: 如果有传播权限就不让删
3. 创建数据库模式的权限
CREATE USER 不是 SQL 标准,各个系统实现不一样
-
如果没有指定创建的新用户的权限,默认该用户拥有 CONNECT 权限。拥有 CONNECT 权限的用户不能创建新用户,不能创建模式,也不能创建基本表,只能登录数据库
-
拥有 RESOURCE 权限的用户能创建基本表和视图,成为所创建对象的属主。但不能创建模式,不能创建新的用户
-
拥有 DBA 权限的用户是系统中的超级用户,可以创建新的用户、创建模式、创建基本表和视图等;DBA 拥有对所有数据库对象的存取权限,还可以把这些权限授予一般用户
4.2.5 数据库角色
数据库角色:被命名的一组与数据库操作相关的权限 - 角色是权限的集合
-
可以为一组具有相同权限的用户创建一个角色
-
简化授权的过程
-
角色的创建
-
给角色授权
-
将一个角色授予其他的角色或用户
-
角色权限的收回
例4.11 通过角色来实现将一组权限授予一个用户
- 首先创建一个角色
- 然后 GRANT 语句给角色权限
- 将角色授予用户
- 可以一次性通过 R1 来回收权限
4.2.6 强制存取控制方法
更高的安全性,适用政府军事部门
-
敏感度标记
- 绝密(Top Secret, TS)
- 机密(Secret, S)
- 可信(Confidential, C)
- 公开(Public, P)
-
主体的敏感度标记称为许可证级别(Clearance Level)
-
客体的敏感度标记称为密级(Classification Level)
-
强制存取控制规则:
-
仅当主体的许可证级别大于或等于客体的密级时,该主体才能读取相应的客体
-
仅当主体的许可证级别小于或等于客体的密级时,该主体才能写相应的客体
-
强度存取控制(MAC)是对数据本身进行密级标记,无论数据如何复制,标记与数据是一个不可分的整体,只有符合密级标记要求的用户才可以操纵数据
-
实现强制存取控制时要首先实现自主存取控制
-
自主存取控制与强制存取控制共同构成数据库管理系统的安全机制
4.3 视图机制
-
把要保密的数据对无权存取这些数据的用户隐藏起来,对数据提供一定程度的安全保护
-
间接的实现支持存取谓词的用户权限定义
例4.14 建立计算机系学生的视图,把对该视图的 SELECT 权限授予王平,把该视图上的所有操作权限授予张明
先建立计算机系学生的视图 CS_Student
在视图上进一步定义存取权限4.4 审计(Audit)
什么是审计
-
启用一个专用的审计日志(Audit Log)
将用户对数据库的所有操作记录在上面
-
审计延利用审计日志
监控数据库中的各种行为,找出非法存取数据的人、时间和内容
-
C2 以上安全级别的 DBMS 必须具有审计功能
审计功能的可选性
-
审计很费时间和空间
-
DBA 可以根据应用对安全性的要求,灵活地打开或关闭审计功能
-
审计功能主要用于安全性要求较高的部门
-
审计事件
- 服务器事件
- 审计数据库服务器发生的事件
-
系统权限
-
对系统拥有的结构或模式对象进行操作的审计
-
要求该操作的权限是通过系统权限获得的
-
-
语句事件
- 对 SQL 语句,如 DDL, DML, DQL 及 DCL 语句的审计
-
模式对象事件
- 对特定模式对象上进行的 SELECT 或 DML 操作的审计
- 服务器事件
-
审计功能
布拉布拉
-
AUDIT 语句和 NOAUDIT 语句
-
AUDIT 语句:设计审计功能
-
NOAUDIT 语句:取消审计功能
-
4.5 数据加密
加密方法:存储加密、传输加密
-
存储加密
-
透明存储加密
数据写到磁盘时对数据进行加密,授权用户读取数据时再对其进行解密
-
非透明存储加密
通过多个加密函数实现
-
-
传输加密(计网的知识)
-
链路加密
在链路层进行加密,传输信息由报头和报文两部分组成,报头和报文均加密
-
端到端加密
- 在发送端加密,接受端解密
- 只加密报文不加密报头
- 所需密码设备数量相对较少,容易被非法监听者发现并从中获取敏感信息
-
4.6 其他安全性保护
-
推理控制
-
隐蔽信道
-
数据隐私保护
第五章 数据库完整性
实体完整性,参照完整性,用户定义完整性前面第二章是讲过的,前面讲的都是概念性的东西,这里是讲具体的 SQL 代码
完整性约束条件在讲SQL表的创建也讲过
5.1 实体完整性
主属性不能取空值
5.1.1 实体完整性定义
例5.1 将Student表中的Sno属性定义为码
两种写法:
(1)在列级定义主码
create table Student (
Sno char(9) primary key,
Sname char(20) not null,
Ssex char(2),
Sage smallint,
Sdept char(20)
);
(2)在表级定义主码
create table Student (
Sno char(9),
Sname char(20),
Ssex char(2),
Sage smallint,
Sdept char(20),
primary key(Sno)
);
更推荐第二种,表级定义,更直观,而且在主码不止一个的时候只能使用表级定义
例5.2 将SC表中的Sno, Cno属性组定义为码
5.1.2 实体完整性检查和违约处理
布拉布拉
5.2 参照完整性
5.2.1 参照完整性定义
- 在create table中用foreign key短语定义哪些列为外码
- 用references短语指明这些外码参照哪些表的主码
5.2.2 参照完整性检查和违约处理
- 一个参照完整性将两个表联系了起来
- 对被参照表和参照表进行增删改操作时可能破坏参照完整性,必须进行检查
处理方法: 1. 拒绝执行
该策略一般设置为默认操作
-
级联操作cascade
删改被操作表的一个元组造成了与参照表的不一致,则删除或修改参照表中的所有造成不一致的元组
-
设置为空值null
删改被操作表的一个元组造成了与参照表的不一致,则将参照表中所有造成不一致的元组的队友属性设置为空值
例5.3 定义Sc中的参照完整性
例5.4 显式说明参照完整性的违约处理示例
5.3 用户定义的完整性
由个人自定
5.3.1 属性上的约束条件
create table时定义属性上的约束条件
- 列值非空 not null
- 列值唯一 unique
- 检查列值是否满足一个条件表达式 check
5.3.1.1 不允许取空值
在定义SC表时,说明Sno, Cno, Grade属性不允许取空值
5.3.1.2 列值唯一
例5.6 建立部门表DEPT,要求部门名称Dname列取值唯一,部门编号Deptno列为主码
5.3.1.3 用check短语指定列值应该满足的条件
例5.7 Student表的Ssex只允许取‘男’或‘女’
create table Student (
Sno char(9) primary key,
Sname char(8) not null,
Ssex char(2) check (Ssex in ('男', '女')),
Sage smallint,
Sdept char(20)
);
这里的check写在一列后面,表示对列的检查
5.3.2 元组上的约束条件
例5.9 当学生性别是男时,其名字不能以Ms.打头
5.4 完整性约束命名子句
5.4.1 完整性约束命名子句
- <完整性约束条件>包括not null, uniquem primary key, foreign key, check

每一列紧贴每一列的约束条件,最后写主码的约束条件
5.4.2 修改表中的完整性限制
使用alter table 语句修改表中的完整性限制,属于DDL语句
*5.5 域中的完整性限制
无
5.6 断言
例5.18 限制数据库课程最多60名学生选修
例5.19 限制一门课最多60名同学选修
5.7 触发器
Trigger 由用户定义在关系表上的一类由时间驱动的特殊过程
5.7.1 定义触发器
create trigger <触发器名>
{before | after} <触发事件> on <表名>
referencing new|old row as <变量>
for each {row|statement}
[when <触发条件>]<触发动作体>
-
表的拥有者才可以在表上创建触发器
-
触发器只能定义在基本表上,不能定义在视图上
- 基本表的数据发生变化时,将激活定义在该表上相应触发事件的触发器
-
触发器类型:
- 行级触发器
- 语句级触发器
例5.21 当对表SC的Grade属性进行修改时,若分数增加了10%,则将此次操作记录到下面表中:SC_U(Sno, Cno, Oldgrade, Newgrade)
5.7.2 激活触发器
5.7.3 删除触发器
第六章 关系数据理论
Tip
第六章关系数据理论,第七章数据库设计,第八章数据库编程
属于数据库的设计与应用开发
前面5章讲的是理论基础
什么样的表可以当数据库的核心数据来用
6.1 问题的提出
关系模式由5部分组成:
这是一个关系模式
- R
- U 为一组属性
- D 为属性组U中的属性所来自的域
- DOM为属性到域的映射
- F为属性组U上的一组数据依赖
数据库可能有的问题:
- 数据冗余
- 增删改异常
为什么会有问题?问题出在数据依赖关系上,不合适的数据依赖关系!
例如在Student(Sno, Sdept, Mname, Cno, Grade)中,Sno, Cno为主码
-
(Sno, Cno, Grade)是一个合适的数据依赖关系, -
但
(Sno, Cno, Sdept, Mname)是一个不合适的数据依赖关系(Sdept, Mname仅与Sno有关,与Cno无关)
数据依赖关系有:
- 函数依赖 Functional Dependency
y=f(x)一个x对应一个y
- 多值依赖 Multi-Valued Dependency
x=f(y)一个x可能对应了多个y
多值依赖是不合适的
所以我们进一步讨论函数依赖关系:
函数依赖关系
-
完全依赖 vs 部分依赖
完全依赖是好的,就是缺一不可的关系
部分依赖(就是有有不止1个主码但是y实际只和其中几个主码有关)不合适,就是Sno, Cno, Sdept, Mname,多此一举
主要就是看结果由谁决定,必须由所有逐渐一起才能定就是完全依赖,一个主键就能决定的是部分依赖关系
-
传递依赖
Cno->专业->系主任就是一个传递的关系 是不合适的 -
平凡依赖 vs 非平凡依赖(x能决定y,但y实际和x没有关系)
废话就是一种平凡依赖,x里已经包含了y,比如张三这个名字里就包含了姓张
非平凡是合适的
以上为这一章的核心概念,后续都是展开的讲解
总结
一个好的表不能发生插入、删除、更新异常,要尽可能少的数据冗余
引发上述的原因是模式中的某些数据依赖
解决方法: 用规范化理论改造关系模式来消除其中不合适的数据依赖
6.2 规范化 重点重点考试必考
6.2.1 函数依赖
6.2.1.1 函数依赖
y = f(x),称为X函数确定Y或Y函数依赖于X,XY为属性列中的子集
先找候选码,候选码中的每个属性都是主属性
6.2.1.2 平凡函数依赖与非平凡函数依赖
对于 X->Y,表示X能决定Y
平凡的函数依赖: 就是\(Y \subseteq X\),相当于一句废话
不平凡的函数依赖: 就是\(Y \not\subseteq X\)
6.2.1.3 完全函数依赖与部分函数依赖
\(R(U)\)中,如果\(X\rightarrow Y\)并且对于\(X\)的任\(X'\)都有\(X' \nrightarrow Y\),则称Y对X完全函数依赖,记作\(X \xrightarrow{F} Y\)
就是说每个x都是必要的,反之则是不完全依赖,记作\(X \xrightarrow{P} Y\)
只有一个主码时不考虑这个
6.2.1.4 传递函数依赖
\(R(U)\)中,如果\(X \rightarrow Y (Y \nsubseteq X), Y \nrightarrow X, Y \rightarrow Z, Z \nsubseteq Y\),则称Z对X传递函数关系
6.2.2 码
Tip
码很重要,码是第一步,有了码才能看码和非码之间的函数依赖关系
超码
若U部分函数依赖于K,即\(K \xrightarrow{P} U\),则K称为超码Surpkey,候选码是最小的超码(超码就是把主码的限制放宽了,候选码加上任意列就是超码)
候选码(码)
能唯一标识关系中的每一个元组的最小属性集合
鬼话:若\(K \xrightarrow{F} U\),则K称为R的一个候选码(Candidate Key)
若关系模式R有多个候选码,则选定其中一个作为主码(Primary key)
主属性与非主属性
包含在任何一个候选码中的属性,称为主属性
不包含在任何码中的属性称为非主属性,或非码属性
- 先找候选码
- 然后分主属性/非主属性
外码
R中属性(组)X不是R的码,但X是另一个关系模式的码,则X是R1的外码
- 全码:整个属性组是码,称为全码
Tip
假设 R(A, B, C, D, E)中,A和B可以确定,B和C也可以确定
那么(A,B), (B,C)也是候选码
其中挑一个就是主码
A, B, C都是主属性
6.2.3 范式
-
1 2 3 BC属于函数依赖范畴
-
4 5属于多值依赖范畴
总结
-
1NF:单元格里不能是个列表。
-
2NF:组合主键时,不能有字段只跟着一半主键跑。
-
3NF:普通字段之间不能互相决定,全都要听主键的。
-
BCNF:任何能决定别人的字段,自己必须有实力当主键
1NF
- 属性不能是组合属性
- 不能表里套表
6.2.4 2NF
什么是2NF
在1NF前提下,所有非主属性都完全函数依赖于任何一个候选码
或者反过来,消除掉非主属性对主属性的部分函数依赖就是2NF
6.2.5 3NF
什么是3NF
非主属性对主属性不要有传递函数依赖
就是不要:主属性->主属性/非主属性->非主属性
6.2.6 BCNF
A: 把所有的函数依赖关系列出来,发现有一组箭头左端不是候选码,就不是BCNF
B: 把主属性都列出来,看主属性内部有没有部分和传递依赖关系
不是说关系模式就一定要升得越高越好,范式理论越高,系统效率越低
例6.5 考察关系模式\(C(Cno, Cname, Pcno)\)
- 只有一个码Cno,没有任何属性对Cno部分依赖或传递依赖,所以\(C \in 3NF\)
- 同时C中Cno是唯一的决定因素,所以\(C \in BCNF\)
- 对于关系模式SC(Sno, Cno, Grade)可做同样分析
例6.6 关系模式S(Sno, Sname, Sdept, Sage)
- 假定Sname也具有唯一性,那么S就有两个码,这两个码都由单个属性组成,彼此不相交
- 其他属性不存在对码的传递依赖和部分依赖,所以\(S \in 3NF\)
- 同时S中除Sno,Sname外没有其他决定因素,所以S也属于BCNF
跳跳跳,不想搞这些范式
6.2.7 多值依赖
给定一对(x, z)值,有一组y的值,这组值仅仅决定于x而与z无关
graph TD
%% 定义节点样式
classDef default fill:#f9fdfa,stroke:#333,stroke-width:2px;
classDef nfNode fill:#e1f5fe,stroke:#0288d1,stroke-width:2px,font-weight:bold,font-size:16px;
%% 定义左侧贯穿的大括号(用子图表示)
subgraph CoreGoal [大前提:消除决定因素非码的非平凡函数依赖]
direction TB
NF1(1NF):::nfNode
NF2(2NF):::nfNode
NF3(3NF):::nfNode
BCNF(BCNF):::nfNode
end
NF4(4NF):::nfNode
%% 定义箭头和文字说明
NF1 -- "消除非主属性对码的部分函数依赖" --> NF2
NF2 -- "消除非主属性对码的传递函数依赖" --> NF3
NF3 -- "消除主属性对码的部分和传递函数依赖" --> BCNF
BCNF -- "消除非平凡且非函数依赖的多值依赖" --> NF4
%% 设置子图样式(模拟图中的虚线框和绿色背景)
style CoreGoal fill:#f2fce8,stroke:#7cb342,stroke-width:2px,stroke-dasharray: 5 5,font-weight:bold
6.2.8 4NF
6.3 数据依赖的公理系统
定义6.11
对于满足一组函数依赖\(F\)的关系模式\(R<U, F>\),其任何一个关系\(r\),若函数依赖\(X \rightarrow Y\)都成立(即\(r\)中任意两元组\(t, s\),若\(t[X] = s[X]\),则\(t[Y] = s[Y]\)),则称逻辑蕴含\(X \rightarrow Y\)
Armstrong 公理系统
- 一套推理规则,是模式分解算法的理论基础
-
用途
- 求给定关系模式的码
- 从一组函数依赖求得蕴含的函数依赖
设\(U\)为属性集总体,\(F\)是\(U\)上的一组函数依赖,于是有关系模式\(R<U, F>\)。对\(R<U, F>\)来说有以下的推理规则:
- A1 自反律:若\(Y \subseteq X \subseteq U\),则\(X \rightarrow Y\)为\(F\)所蕴含
- A2 增广律:若\(X \rightarrow Y\)为\(F\)所蕴含,且\(Z \subseteq U\),则\(XZ \rightarrow YZ\)为\(F\)所蕴含
- A3 传递率:若\(X \rightarrow Y\)及\(Y \rightarrow Z\)为\(F\)所蕴含,则\(X \rightarrow Z\)为\(F\)所蕴含
根据A1, A2, A3这3条推理规则可以得到下面三条推理规则
- 合并规则:
- 伪传递规则
- 分解规则
引理6.1
\(X \rightarrow A_1 A_2 ...A_k成立的充要条件是X \rightarrow A_i 成立(i = 1, 2, ..., k)\)
定义6.12
在关系模式\(R<U, F>\)中为\(F\)所逻辑蕴含的函数依赖的全体叫做\(F\)的闭包,记为\(F^+\)
是函数依赖关系的集合,以F为条件,能得到的所有关系
定义6.13
设\(F\)为属性集\(U\)上的一组函数依赖,\(X、Y \subseteq U, X_F^+ = \{ A \mid X \rightarrow A能由F根据Armstrong 公理导出 \}\),\(X_F^+\)称为属性集\(X\)关于函数依赖集\(F\)的闭包
定义6.14
两个函数依赖集等价是指他们的闭包等价
6.4 *模式的分解
第七章 数据库设计
7.1 数据库设计概论
7.1.1 数据库设计的特点
7.1.2 数据库设计方法
7.1.3 数据库设计的基本步骤
分6个阶段!
- 需求分析
- 概念结构设计 画E-R图
- 逻辑结构设计
- 物理结构设计
- 数据库实施
- 数据库运行和维护
7.1.4 数据库设计过程中的各级模式
7.2 需求分析
7.3 概念结构设计
7.3.1 概念结构
7.3.2 E-R 模型
7.3.2.1 实体间的联系
两个实体型之间的联系
- 一对一联系
- 一对多联系
- 多对多联系
graph TD
A[实体型A] ---|1/m| B{联系名}
B -- 1/n --- C[实体型B]
两个以上实体型之间的联系
也存在一对一、一对多、多对多的联系
graph TD
A[课程]---|1|B{讲授}
B---|m|C[教师]
B---|n|D[参考书]
单个实体型内的联系
同一个实体集内的各实体之间也可以存在一对一、一对多、多对多的联系
graph TD
A[职工]---|1|B{领导}
B---|n|A
*7.3.3 拓展的E-R模型
*7.3.4 UML
7.3.5 概念结构设计
7.4 逻辑结构设计
7.4.1 E-R图向关系模式的转换
7.4.2 数据模型的优化
7.4.3 设计用户子模式
第八章 数据库编程
SQL 与 高级语言的结合
SQL 擅长处理大规模数据,高度非过程化
高级语言擅长过程,但不擅长处理大规模数据
所以可以把SQL作为函数嵌入到高级语言里
8.4 之后的章节,是考虑不同的部门可能使用的数据库都不是一个企业开发的
8.1 嵌入式 SQL
8.1.1 嵌入式SQL的处理过程
区分主语言和SQL语句,所有SQL语句必须加前缀EXEC SQL
例如在C语言中:
8.2 过程化 SQL
8.3 存储过程和函数
又返回值的就是函数,否则就是存储过程
8.3.1 存储过程
由过程化SQL书写的过程,经编译和优化后存储在数据库服务器中,使用时只要调用即可
8.3.2 存储过程的用户接口
- 创建存储过程
例8.8 从账户1转指定数额的款项到账户2中
create procedure
transfer (inAccount INT, outAccount INT, amount FLOAT)
/*定义存储过程,和参数*/
as declare /*定义变量*/
totalDepositOut Float;
totalDepositIn Float;
inAccountnum INT;
begin
select Total into totalDepositOut from Account
where accountnum=outAccount;
if totalDepositOut is null then
rollback; // 如果账户不存在或者账户中五存款就回滚
return;
end if;
if totalDepositOut < amount then
rollback;
return;
end if;
select Accountnum into inAccountnum from Account
where accountnum = inAccount;
if inAccount is null then
rollback;
return;
end if;
update Account set total=total-amount
where accountnum=outAccount
update Account set total=total+amount
where accountnum=inAccount;
commit;
end;
- 执行存储过程
刚才是写,现在要用了:
就跟调用函数一样
- 修改存储过程
只能修改名字,不然就重新定义一个
- 删除存储过程
8.3.3 函数
- 函数的定义语句格式
- 函数的执行语句格式
- 修改函数
重命名:
重新编译