数据库原理(2)

目录

数据库原理二

第五章 规范化设计

关系模式的设计问题

关系模式的外延和内涵

一个关系模型包括外延和内涵两个方面的内容。

  • 外延:关系、表或当前值。

  • 内涵:对数据的定义以及对数据完整性约束的定义。

泛关系模式与数据库模式

(泛) 关系模式 R(U)

  • R:关系名字
  • U:所有属性的全集
  • 泛关系模式:所有属性组成的关系模式 R(U)
  • 泛关系:当前值 r
  • 数据库:$R_i$ 的实例

实际使用时,用一个关系模式的集合 $\rho = { R_1,\dots,R_k}$ 来代替 R(U),其中 $R_1 ∪ R_2 ∪··· ∪R_n = R(U)$,$\rho$ 称为数据库模式

关系模式的冗余和异常问题

数据冗余:同一个数据重复存储多次。

操作异常:修改异常,插入异常,删除异常

image-20220308151401739 image-20220308151410230 image-20220308151420363 image-20220308151430051 image-20220308151446399

函数依赖

函数依赖 FD 的定义

通俗定义:(X 和 Y 为属性或属性组)当 X 有一个确定值时,Y 一定有一个唯一的值与其对应

严格定义:

image-20220308151831420

或者说,属性 X 函数决定属性 Y,记作 X→Y。 其中 X 叫决定因素,Y 叫被决定因素。

此定义可简单表述为:如果属性 X 的值决定属性 Y 的值,那么属性 Y 函数依赖于属性 X。

换一种说法是,如果知道 X 的值,就可以获得 Y 的值。

  • 不依赖:$X \nrightarrow Y$

  • 互相依赖:$X \leftrightarrow Y$

image-20220308153147662

FD 的逻辑蕴涵、函数依赖集 F 的闭包

逻辑蕴涵:由函数依赖集 F 能够推出的某依赖逻辑蕴涵于 F

函数依赖集 F 的闭包:F 能推出的所有依赖组成的集合

image-20220308153351885

逻辑蕴涵:{A→B,B→C} 逻辑蕴涵 A→C

函数依赖的推理规则

Armstrong 公理系统
  1. 自反性(以大推小):$若 Y\sube X \sube U, 则 X \rightarrow Y 在 R 上成立。$
  2. 增广性(两边加):$若 X \rightarrow Y 在 R 上成立,且 Z \sube U, 则 XZ \rightarrow YZ 在 R 上成立。$
  3. 传递性:$若 X \rightarrow Y 和 Y \rightarrow Z 在 R 上成立,则 X \rightarrow Z 在 R 上成立。$
image-20220308153406619
另外三个推理规则

平凡的 FD:以大推小

image-20220602100443663

FD 与关键码的联系

包含在任何一个候选键中的属性成为主属性

不包含在任何一个候选键中的属性成为非主属性

image-20220308160717162
找候选键的方法

小定理:

  • 不在函数依赖右部出现的属性,一定是
  • 只在函数依赖右部出现的属性,一定不是
image-20220308161331535 image-20220308161440201 image-20220308161447918

属性集的闭包

人话:属性 X(作为左值)可以推出的所有属性的集合

image-20220308161457792
求属性集的闭包

其实不用这么麻烦,暴力找也是可以的。。

image-20220308161928927 image-20220308161942842 image-20220308162000436 image-20220308162008294 image-20220308162421014

FD 的最小依赖集

函数依赖集的等价

等价:两者闭包相等

image-20220308162436812
最小函数依赖集

最大函数依赖集就是闭包

  • 保证右边都是单属性

  • 消除左边的多余属性

  • 消除多余的函数依赖

image-20220315151127771
image-20220315151412567 image-20220315151417206 image-20220315153009173 image-20220315153021337

关系模式的分解特性

模式分解问题

分解:把一张表拆成多张表

投影

人话:有函数依赖集 F~i~,其中的所有元素都属于子集 U~i~,则称 F~i~ 为 F 在 U~i~ 上的投影

image-20220315154036857
无损连接性与函数依赖保持性
image-20220315154427612

无损分解

无损连接:分解后的表进行自然连接之后的表与原表的内容不多不少

image-20220315154616981

无损分解的测试方法

image-20220315160031794 image-20220315160151601 image-20220315160202135 image-20220315160209405 image-20220315160217009

image-20220315160236362image-20220315160241704

第二种方法

只分解成两个子模式时适用

image-20220315161148857 image-20220315161820582 image-20220315161848712

保持函数依赖的分解

函数依赖保持性:F 在 Z 这个属性集合上的投影得到的小函数依赖集们的并集是否与 F 等价

image-20220315161858815

判断函数依赖保持性的方法

  1. 求每个分解模式在 F 上的投影
  2. 若投影的并 = F,则保持
image-20220315161907624 image-20220315161915181 image-20220315161923688

关系模式的范式

码 = 候选键,本质上是一个或一堆属性

https://markdown-1303167219.cos.ap-shanghai.myqcloud.com/853012-20181109110730391-1699550272.png

第一范式 1NF

反例
image-20220322150648406 image-20220322150805914 image-20220322150818141
定义

原子性:每一个属性都不可分解

image-20220322150848377
修改后的例子
image-20220322150953681 image-20220322151003707

第二范式 2NF

定义

第一范式有部分依赖的问题,而第二范式消除了部分依赖

在满足第一范式的条件下,其他属性都必须完全依赖于某个候选键

  • 部分依赖:$X\rightarrow Y,且存在 X 的真子集 x’,满足 x’\rightarrow Y$
  • 完全依赖/ 左部不可约依赖:$X\rightarrow Y,且不存在 X 的真子集 x’,满足 x’\rightarrow Y$
image-20220322151718007 image-20220322151741366

第三-范式 3NF

第二范式会有传递依赖的问题,而第三范式消除了传递依赖

✔️ 在满足第一范式的前提下,每一个非主属性都不传递依赖于候选键(主属性)

个人理解:不满足第三范式的情况——存在非主属性 C 依赖于非主属性 B

跟 BCNF 相近的定义:对于 F 中每个非平凡 FD X->Y,都有 X 是 R 的超键,或 Y 的每个属性都是主属性(表明主属性间可能有传递依赖)。即每一个决定因素(左部)都包含码

image-20220322152917085 image-20220322152926667
image-20220322154517415 image-20220322154654654

巴克斯范式 BCNF

消除主属性之间的(部分函数依赖和)传递函数依赖

✔️ 人话:对于 F 中每个非平凡 FD X->Y, 都有 X 是 R 的超键。即每一个决定因素(左部)都包含码

跟 3NF 相近的定义:满足第一范式的前提下,每一个属性都不传递依赖于候选键(主属性)

image-20220322160029125 image-20220322160222855 image-20220322160458916

分解成 BCNF 模式集的方法

只能保持无损分解,不一定保持函数依赖。

  1. 置初值:ρ = {R}。

  2. ρ 已经满足 BC 范式,则结束。

  3. 找到左边没有码的依赖 X->A

    1. 把 XA 单独放在一个模式 S~1~(这个模式必满足 BCNF)
    2. 把 A 从 U 里面删除,剩余属性组成一个新模式 S~2~,
  4. 继续步骤 3,分解 S~2~,直到都满足 BCNF。

  5. 结束,输出 ρ。

image-20220322161210743 image-20220322161220977

另一种方法:

https://markdown-1303167219.cos.ap-shanghai.myqcloud.com/image-20220327171535911.png

分解成 3NF 模式集的方法

保持函依赖分解题,先求最小依赖集。

依赖两侧未出现,分成子集放一边,剩余依赖变子集。

若要连接成无损,再添候选做子集。

算法一

保持函数依赖 ρ 的 3NF 模式集

输入:R(U) + F~min~

  1. 若 F~min~ 中只有一个函数依赖 X -> A , 且 {X, A} = U ,则停止
  2. 所有 F~min~ 中没有出现的属性,放在一个单独的模式。
  3. F~min~ 中的每一个 X -> A,放在同一分组 R~i~ = XA
  4. 分解结束,输出 ρ
image-20220322161229166 image-20220322161233794 image-20220322161242727
算法二

既保持函数依赖又无损链接 ρ 的 3NF 模式集

输入:U + F~min~

  1. 算法 1 得到一个模式集
  2. 若现有的模式中不存在包含候选键的模式,则将候选键作为一个模式加入模式集。
image-20220531115002045 image-20220322161936938 image-20220322161941646

第七章 数据库设计

数据库设计概述

软件生存期

定义:指从软件的规划、研制、实现、投入运行后的维护,直到它被新的软件所取代而停止使用的整个期间。

六个阶段:规划阶段、需求分析阶段、设计阶段、程序编制阶段、调试阶段、运行维护阶段

数据库系统生存期

  • 数据库应用系统:以数据库为基础的信息系统。具有对信息的采集、组织、加工、抽取和传播等功能。

  • 数据库工程:数据库应用系统的开发。

  • 数据库系统生存期:数据库应用系统从开始规划、设计、实现、维护到最后被新的系统取代而停止使用的整个期间。

七个阶段
  1. 规划阶段
    • 必要性和可行性分析。确定数据库系统的地位,以及数据库间联系。
  2. 需求分析阶段
    • 分析用户需求
    • 信息要求(数据库中存储哪些数据)
    • 处理要求(需要的处理功能,响应时间要求,批/联机处理)
    • 安全性和完整性要求
  3. 概念设计阶段
    • 表达用户整体要求,且独立于 DBMS 和硬件结构。
  4. 逻辑设计阶段(设计 ER 图)
    • 数据库逻辑结构设计:ER 图 => DBMS 的 DDL 转换为逻辑数据库结构
    • 应用程序设计:DBMS 的 DML 进行结构式的程序设计。
  5. 物理设计阶段(设计表)
    • 物理数据库结构的选择
    • 逻辑设计中程序模块说明的精确化(开发)。
    • 成果:一个完整的,能实现的数据库结构。
  6. 实现
  7. 运行维护
    • 收集和记录系统实际运行的数据。

https://markdown-1303167219.cos.ap-shanghai.myqcloud.com/image-20220529145819593.png

规划

规划阶段完成的任务

  • 确定系统的范围
  • 确定开发工作所需要的资源
  • 估计软件开发的成本
  • 确定项目的进度

可行性分析报告

规划工作完成后,写出详尽的可行性分析报告和数据库系统规划纲要

内容包括:信息范围、信息来源、人力资源、设备资源、软件及支持工具资源、开发成本估算、开发进度计划、现行系统向新系统过渡计划等。

规划送决策部门评审。

需求分析

需求描述与分析

  1. 对系统的整个应用情况做全面的详细的调查确定企业组织的目标
  2. 收集支持系统总的设计目标的基础数据和对这些数据的要求确定用户的需求
  3. 并把这些要求写成用户和数据库设计者都能接受的文档。

需求分析阶段的输入和输出

  1. 输入:总体信息要求(数据本质和概念上联系),处理要求(数据处理),系统要求
  2. 输出:需求说明书(数据流图 + 数据字典)

需求分析的步骤

  1. 分析用户活动,产生用户活动图(即用户的业务流程图
  2. 确定系统范围,产生系统范围图(即确定人机界面);
  3. 分析用户活动所涉及的数据,产生数据流图(数据的流向及加工);
  4. 分析系统数据,产生数据字典。

数据流图:→ 数据流;$\bigcirc$ 加工 / 处理;= 文件;$\square$ 外部实体

数据字典:

  • 定义:对系统中数据的详尽描述,提供了对数据库数据描述的集中管理。
  • 内容:数据项,数据结构,数据流,数据存储,加工过程
  • 功能:存储和检索各种数据描述,为 DBA 提供有关的报告。
  • 在需求分析阶段建立,并在数据库设计过程中不断改进、充实和完善。

概念设计

目标:产生反映企业组织信息需求的数据库概念结构(概念模式)。

概念模式独立于数据库逻辑结构,也独立于支持数据库的 DBMS。

概念设计的必要性

  1. 各阶段的任务相对单一化,设计复杂程度大大降低,便于组织管理。
  2. 不受特定的 DBMS 的限制,也独立于存储安排和效率方面的考虑,比逻辑模式更稳定。
  3. 不含具体 DBMS 附加技术细节,用户理解容易,可以更准确反应用户的信息需求。

概念模型

  1. 是对现实世界的抽象和概括。
  2. 应简洁,明晰,独立于机器,容易理解。
  3. 应易于变动。
  4. 应很容易向关系,层次,网状等各种数据模型转换。

概念设计的主要步骤

  1. 进行数据抽象,设计局部概念模式(“聚集” + “概括”)
  2. 将局部概念模式综合成全局概念模式(解决冲突:消除冗余,统一命名)
  3. 评审(用户评审 + DBA 和应用开发人员评审)

数据抽象

  1. 抽象:对实际的人、物、事或概念的人为处理,抽取人们关心的共同特性,忽略非本质的细节,将这些特性用各种概念精确地加以描述,这些概念组成了某种模型。
  2. 两种形式:
    • 抽象对象:系统状态的抽象
    • 抽象运算:系统转换的抽象
  3. 聚集:笛卡尔积,形成对象之间的一个联系对象。
    • 聚集层次表示:“是……的一部分” (is part of) 的关系。
  4. 概括:从一类对象形成一个对象。
    • 概括层次表示:“是……一种” (is a) 的关系。
  5. 数据抽象层次
    • 每个对象既可以是聚集对象,也可以是概括对象。
    • 反复进行数据抽象,形成层次关系。

https://markdown-1303167219.cos.ap-shanghai.myqcloud.com/image-20220529145838801.png

ER 模型的操作

ER 模型的操作:在利用 ER 模型进行数据库概念设计的过程中,常常对 ER 图进行的种种变换。(实体类型、联系类型和属性的分裂、合并和增删······)

实体类型的分裂
  1. 垂直分割:把一个实体类型的属性分成若干组,然后按组形成若干实体类型。 键必须在所有实体中体现。

https://markdown-1303167219.cos.ap-shanghai.myqcloud.com/image-20220529145847409.png

  1. 水平分割:分裂成互补相交的子类。 e.g. 教师 => 男教师 + 女教师

https://markdown-1303167219.cos.ap-shanghai.myqcloud.com/image-20220529145852716.png

实体类型的合并
  1. 水平合并,垂直合并。
  2. 是否会产生新联系视情况而定。
联系类型的分裂

一个联系类型可分裂成几个新联系类型。新联系类型可能和原联系类型不同。

https://markdown-1303167219.cos.ap-shanghai.myqcloud.com/image-20220529145900817.png

联系类型的合并

合并的联系类型必须是定义在相同的实体类型组合中,否则,不合法。

https://markdown-1303167219.cos.ap-shanghai.myqcloud.com/image-20220529145906488.png

采用 ER 方法的数据概念设计

第一步:设计局部 ER 模式:

  1. 确定局部结构范围划分;
  2. 实体定义;
  3. 联系定义。

第二步:设计全局 ER 模式:

  1. 确定公共实体类型;(同名实体类型;相同主键的实体)
  2. 局部 ER 模式的合并;
  3. 消除冲突 (属性冲突,结构冲突,命名冲突)

第三步:全局 ER 模式的优化原则:

  1. 相关实体类型的合并:1:1 的实体合并,部分相同键的实体
  2. 冗余属性的消除;
  3. 冗余联系的消除。

逻辑设计

数据库的逻辑设计就是把概念设计得到的数据库模型,转化为具体的 DBMS 所能接受的数据库逻辑结构,包括数据库模式和外模式

逻辑设计环境

  1. 输入
    1. 独立于 DBMS 的概念模式:局部,全局概念模式(概念设计阶段)
    2. 处理需求:业务活动分析结果(需求分析阶段)
    3. 约束条件
    4. DBMS 特性
  2. 输出
    1. DBMS 可处理的模式:说明
    2. 子模式
    3. 应用程序设计指南
    4. 物理设计指南:完全文档化的模式和子模式。

逻辑设计的步骤

https://markdown-1303167219.cos.ap-shanghai.myqcloud.com/image-20220529152543667.png

ER 模型象关系模型的转换

ER 模型转换为关系模型的一般规则

  1. 实体类型的转换:1 个实体 1 张表。

  2. 联系类型的转换

    • 1:1:任意一端加入另一端的主键,作为外键。
    • 1:N:N 端加入 1 端主键,作为外键。
    • 弱实体 1:N:N 端为弱实体 N 端中加入 1 端主键,作为外键。且 N 端主键 = 1 端主键 + N 端外键
    • M:N:新增一张表,主键为两端的外键构成。
  3. 超类和子类的转换规则:子类 = 父类主键 + 新增属性

关系数据库的逻辑设计

https://markdown-1303167219.cos.ap-shanghai.myqcloud.com/image-20220529145935339.png

  1. 导出初始关系模式
  2. 运用模式设计理论,对初始关系模式进行规范化处理
    1. 确定规范级别,3NF / BCNF
    2. 实施规范化处理
  3. 模式评价:功能 + 性能
  4. 模式修正

物理设计

  1. 物理设计:对于给定的基本数据模型选取一个最适合应用环境的物理结构。
  2. 数据库的物理结构:数据库的存储记录格式,存储记录安排,存取方法。
  3. 物理设计分五步完成
    1. 存储记录结构设计:记录的组成、数据项的类型、长度,以及逻辑记录到存储记录的映射。
    2. 确定数据存放位置:把经常同时被访问的数据组合在一起。
    3. 存取方法的设计:主存取路径,辅存取路径。
    4. 完整性和安全性考虑
    5. 程序设计

数据库的实现

  1. 数据库的实现阶段: 根据逻辑设计和物理设计的结果,在计算机系统上建立起实际数据库结构、装入数据、测试和试运行的过程。
  2. 实现阶段主要有三项工作
    1. 建立实际数据库结构
    2. 装入试验数据对应用程序进行调试
    3. 装入实际数据,进入试运行状态

数据库的运行和维护

运行维护阶段主要有四项工作

  1. 维护数据库的安全性与完整性
  2. 监测并改善数据库运行性能
  3. 根据用户要求对数据库现有功能进行扩充
  4. 及时改正运行中发现的系统错误

第八章 数据库管理

事务的概念

事务的定义

事务是构成单一逻辑工作单元的操作集合。DBS 必须保证事务正确,完整的执行

事务是由若干数据库操作组成的一个逻辑工作单位,是一个不可分割的工作单位。

  • 一个应用程序可以包括多个事务。
  • 事务以 BEGIN TRANSACTION 语句的成功执行开始,以 COMMITROLLBACK 语句的成功执行结束。
    • COMMIT(提交)语句表示一事务的全部操作都已成功,它对 DB 的所有更新可真正写到 DB 中。
    • ROLLBACK(回退)语句表示事务没有成功地完成全部操作,系统将撤消该事务对 DB 已作的更新。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# 银行转账事务
T:BEGIN TRANSACTION;			/* 事务开始语句 */
  read(A);
  A := A - 50;
  write(A);
  if (A < 0): ROLLBACK;			/* 事务回退语句 */
  else {
  		read(B);
  		B := B + 50;
  		write(B);
  		COMMIT;}				/* 事务提交语句 */

事务的性质(ACID)

事务有四个重要性质:原子性、一致性、隔离性和持久性。通常称为 “ACID 性质”。

  • 原子性(atomicity)
    • 事务对数据库的更新要么全部起作用,要么完全不起作用。(不可分割)
    • DBMS 的事务管理子系统
  • 一致性(consistency)
    • 一个事务独立执行的结果,应保持数据库的一致性。即数据不会因事物的执行而遭受破坏
    • 程序员(正确地编写事务)DBMS 的完整性子系统
  • 隔离性(isolation )
    • 事务相互隔离,在多个事务并发执行时,任一事务的更新操作在该事务成功提交前对其他事务都是不可见的。
    • DBMS 的并发控制子系统
  • 持久性(durability)
    • 事务一旦成功提交,其对数据库的更新就永久有效,不会因系统崩溃等而丢失。
    • DBMS 的恢复管理子系统

事物的状态变迁

https://markdown-1303167219.cos.ap-shanghai.myqcloud.com/image-20220503151741223.png

数据库的恢复

数据库恢复的定义

恢复的定义:恢复管理子系统采取一些列的措施保证在任何情况下保持事务的原子性和持久性,确保数据不丢失、不破坏。

数据库的可恢复性:系统能把数据库从被破坏、不正确的状态、恢复到最近一个正确的状态。

数据库恢复的基本原则和实现方法

基本原则冗余(数据重复存储)

实现方法

  • 备份:定期对数据库复制或转储(静态转储和动态转储,海量转储和增量转储)。
  • 日志:执行事务时,记录其开始、结束和对 DB 的每次更新操作。

发送故障时,分情况处理

  • 数据库破坏:复制最近一次数据到数据库,利用日志 “重做” 以同步。
  • 数据库完好,数据损坏:利用日志 “撤销” 处理。
image-20220503152715965

故障类型

  • 事务故障

    • 非预期事务故障:运算错误、数据错误、死锁等,故障事务夭折
    • 可预期事务故障:在事务中可预期出错的地方所加的 ROLLBACK 语句
  • 系统故障(软故障)

    • 引起系统停止运转随之要求重新启动的事件。
    • 影响正在运行的事务,主存内容丢失,但不破坏数据库。
    • 硬件、系统软件出错,停电等,事务执行被打断,内存中数据被破坏
  • 介质故障(硬故障)

    • 物理损坏,磁盘数据丢失。
    • 磁头、磁盘控制器或磁盘损坏,盘上数据丢失,病毒破坏等,DB 遭破坏

恢复方法

当系统运行过程中发生故障,利用数据库后备副本和日志文件将数据库恢复到故障前的某个一致性状态。不同故障其恢复技术不一样

事务故障的恢复

事务故障的恢复是由系统自动完成的,不需要用户干预。

事务故障是指事务在运行至正常终止点前被终止,此时恢复子系统应撤销(UNDO)此事务已对数据库进行的修改

恢复步骤(其实就是 undo 的具体操作)

  1. 反向扫描日志文件(即从最后向前扫描日志文件)
    • 查找该事务的更新操作。
  2. 对该事务的更新操作执行逆操作。
    • 即将日志记录中“更新前的值”写入数据库
      • 若记录中是插入操作,则相当于做删除操作
      • 若记录中是删除操作,则做插入操作
      • 若是修改操作,则用修改前值代替修改后值。
  3. 继续反向扫描日志文件,查找该事务的其他更新操作,并做同样处理。
  4. 如此处理下去,直至读到此事务的开始标记,事务故障恢复就完成了
系统故障的恢复

系统故障的恢复也由系统自动完成的,不需要用户干预。

系统故障造成数据库不一致状态的原因有两个

  • 未完成事务对数据库的更新已写数据库
  • 已提交事务对数据库的更新还留在缓冲区没来得及真正写入数据库。

恢复办法

  • 撤销 undo 故障发生时未完成的事务
  • 重做 redo 已完成的事务(使其写入数据库)

恢复步骤

  1. 正向扫描日志文件 (即从头开始扫描日志文件),找出在故障发生前
    • 已提交事务 (既有 <Ti, START> 记录,也有 <Ti, COMMIT> 记录),将其事务标识记入重做队列
    • 尚未完成的事务 (有 <Ti, START> 记录,无 <Ti,COMMIT> 记录), 将其事务标识记入撤销队列
  2. 对撤销队列中的各个事务进行撤销(UNDO)处理
    • 反向扫描日志文件,对每个 UNDO 事务的更新操作执行逆操作,即将日志记录中“更新前的值”写入数据库
  3. 对重做队列中的各个事务进行重做(REDO)处理
    • 正向扫描日志文件,对每个 REDO 事务重新执行登记操作,即将日志记录中“更新后的值”写入数据库
介质故障的恢复

在发生介质故障和遭受病毒破坏时,磁盘上的物理数据库遭到毁灭性破坏。此时恢复的过程如下

  1. 重装转储的副本,恢复数据库到最近一次转储的正确(一致)状态。
  2. 在日志中找出转储以后所有已提交的事务。
  3. 对已提交事务 REDO 处理。
image-20220503161657955

检查点机制

感觉就是系统故障的恢复的优化

检查点(Checkpoint)方法 :DBMS 定时设置检查点,在检查点时刻才真正做到把对 DB 的修改写到磁盘,并在日志文件写入一条检查点记录。

恢复方法

  1. 根据日志文件建立重做队列和事务撤消队列。
  2. 对重做队列中的事务进行 REDO 处理,对撤消队列中的事务进行 UNDO 处理
image-20220531221346786
检查点方法

DBMS 定时设置检查点,在检查点时,做下列事情

  1. 将日志缓冲区中的日志记录写入磁盘
  2. 将数据库缓冲区中修改过的缓冲块内容写入磁盘
  3. 写一个检查点记录到磁盘,内容包括
    • 检查点时刻,所有活动事务
    • 每个事务最近日志记录地址
  4. 把磁盘中日志检测点记录的地址写入“重新启动文件中”
检查点恢复步骤 ✔️
  1. 正向扫描日志文件,建立事务重做队列和事务撤消队列
    • 将已完成的事务加入重做队列
    • 未完成的事务加入撤销队列
    • 做完的重做,没做完的别做了
  2. 对撤销队列做 UNDO 处理的方法是
    • 反向扫描日志文件,根据撤销队列的记录对每一个撤销事务的更新操作执行逆操作,使其恢复到原状态
  3. 对重做队列做 REDO 处理的方法是
    • 正向扫描日志文件,根据重做队列的记录对每一个重做事务实施对数据库的更新操作

运行记录优先原则

运行记录优先原则包括两点

  • (先写日志,后写 DB)将一个更新结果写到 DB 中前,必须确保先在日志中成功登记了这个更新。
  • (写全日志,才 COMMIT)直至对一事务的日志登记全部完成,方能够允许该事务完成 COMMIT 处理。

这个原则确保了发生故障后能够根据日志对事务进行 REDO 或 UNDO。

数据库的并发控制

并发操作带来三个问题

为了充分利用数据库这个共享资源,DBMS 允许多个事务并发地存取数据库。

如果不对并发操作进行恰当的控制,可能导致如下的数据不一致性问题:

  • 丢失更新问题:(更新被覆盖,同时写时会发生)一事务所作的更新操作因另一事务的操作而丢失。
  • 不一致分析问题:(前后读取不一致,读时写会发生)指事务从数据库中读取了处于不一致状态的数据,并因此进行了不一致的分析。
  • 读 “脏数据” 问题(读取的数据被撤销,读时写会发生):又称为未提交依赖,指一事务取用了别的事务未提交随后又被撤消的数据。
丢失更新

Lost Update

指事务 Ti 与事务 Tj 从数据库中读入同一数据并修改,事务 Tj 的提交结果破坏了事务 Ti 提交的结果,导致事务 Ti 的修改被丢失。

image-20220516210506608
不一致分析

不可重复读 nonrepeatable read

指事务 Ti 读取数据后,事务 Tj 执行更新操作,使事务 Ti 无法再读取前一次结果

image-20220516211547543
读“脏”数据

diriy read

事务 Ti 修改某一数据,并将其写回磁盘,事务 Tj 读取同一数据后,事务 Ti 由于某种原因被撤销,这时事务 Ti 已修改过的数据恢复原值,事务 Tj 读到的数据就与数据库中的数据不一致,是不正确的数据,称为“脏”数据。

如果事务 T~j~ 读取脏数据后又进行了更新操作,实际上是无效的,此时破坏了数据库的完整性。

image-20220516212059994

封锁机制

封锁是实现并发控制的重要技术。

所谓封锁,是指事务向系统发出对某数据对象加锁的请求,以取得对该对象一定的控制权。

基本的封锁有两类:

  • 排它型封锁(写锁,X 封锁):一个事务对数据对象加了 X 锁后,在它释放 X 锁之前不允许其他事务再对该数据对象加任何锁。
  • 共享型锁(读锁,S 封锁) :一个事务对数据对象加了 S 锁后,允许其他事务再对该数据对象加 S 锁,但在它释放 S 锁之前不允许其他事务加 X 锁。
image-20220516213308761
排它型封锁

PX 协议主要内容是:

  • 事务若要更新数据 R,则必须先提出对此 R 的 X 封锁请求;(XFIND R
  • 事务如果未获准 X 封锁,那么进入等待状态,直至获准在此数据对象上的 X 封锁,才能继续执行。

PX 协议可以解决因多事务同时更新同一数据对象而引起的更新丢失问题。

PXC 协议 是在 PX 协议上再加一规定:解除 X 锁的操作合并到事务的结束(COMMIT 或 ROLLBACK)操作中。

PXC 协议可以解决更新丢失问题。

image-20220516212541732
共享型封锁

PS 协议,其主要内容是:

  • 事务若要存取数据 R,则必须先提出对 R 的 S 封锁请求;(SFIND R
  • 事务如果未获准 S 封锁,那么进入等待状态,直至获准在此数据对象上 S 封锁,才能继续执行;
  • 事务在更新数据前必须先将它在该数据对象上的 S 封锁升级为 X 封锁。 (UPDX R

**PSC 协议 **是在 PS 协议上再加一规定:解锁操作合并到事务的结束(COMMIT 或 ROLLBACK)操作中。

PSC 协议可以解决丢失更新、读 “脏数据” 和不一致分析问题。

image-20220516212728567

活锁和死锁

恰当地运用封锁技术,可以保证并发调度的正确性、有效地避免数据不一致,但有可能引起活锁和死锁问题。

活锁

出现某个事务永远处于等待状态得不到执行的现象。

例子:写者一直被不断到来的读者堵着

避免活锁的一个简便方法是采用 “先来先服务” 排队的策略。封锁子系统按请求在时间上的先后次序对事务排序,数据对象上原有的锁一释放,即执行队列中第一个事务的封锁请求。

image-20220516213848559
饿死

对某数据,S 锁永远存在,没有机会上 X 锁。

解决:授权加锁:T2 对 Q 加锁

  • 不存在在数据项 Q 上持有 X 锁的其他事务。
  • 不存在等待对数据项 Q 加锁且先于 T2 申请加锁的事务。

这个定义跟活锁太像了,很怪

死锁

出现若干事务因循环等待而无法继续执行的现象。

例: 两个事务 T1 和 T2 已分别封锁了数据 D1 和 D2。 T1 和 T2 由于需要各自分别申请封锁 D2 和 D1,但是由于 D2 和 D1 已被对方封锁,因而 T1 和 T2 只能等待。 而 T1 和 T2 由于等待封锁而不能结束,从而使对方的封锁申请也永远不能被选中,这就形成了死锁。

死锁的诊断:DBMS 周期地测试系统中是否出现了死锁。用事务依赖图的形式可以测试系统中是否存在死锁。如果在事务依赖图中,沿着箭头方向存在一个循环,那么表示已出现死锁现象。

image-20220516214047843

并发事务的可串行化调度

事务的调度、串行调度和并发调度
  • 调度:事务的执行次序

  • 串行调度:多个事务依次执行

  • 并发调度:设法(例如利用分时的方法)使多个事务同时被处理(即交错执行)

在应用环境中,事务的任一串行调度都是有效的(正确的),但是事务的并发调度不一定是正确的,有可能产生前面提到的不一致性问题。

image-20220516214740738 image-20220516214754739 image-20220516214801766 image-20220516214807748 image-20220516214840390

了保证并行操作的正确性,DBMS 的并行控制机制必须提供一定的手段来保证调度是可串行化的。

从理论上讲,在某一事务执行时禁止其他事务执行的调度策略一定是可串行化的调度,这也是最简单的调度策略,但这种方法实际上是不可行的,因为它使用户不能充分共享数据库资源。

可串行化与两端封锁协议

可串行化:如果一个并发调度与某一串行调度具有相同的执行结果,那么称这个并发调度是可串行化的调度(即正确的并发调度),否则是不可串行化的调度。

两段封锁协议

  • 事务在对数据对象存取之前必须先获得对此数据对象的封锁
  • 事务在解除了一个锁之后不能再获得任何其他封锁

要点

  • PXC 和 PSC 协议可以看作两端封锁协议的加强形式

  • ⭐ 若所有事务都遵守两段封锁协议,则对这些事务的任何并发调度策略都是可串行化的;

  • 但若并发事务的一个调度是可串行化的,并不一定所有事务都符合两段封锁协议。

  • 两段封锁协议与防止死锁的一次封锁法是不同的。一次封锁法符合两段封锁协议,但两段封锁协议并不要求一

    次封锁法。因此,遵守两段封锁协议的事务也有可能发生死锁。

封锁粒度:封锁对象的规模称为封锁粒度(Granularity)。

SQL 中事务的存取模式和隔离级别

事务的存取模式

  • READ ONLY(只读型)
  • READ WRITE(读写型)

事务的隔离级别

  • SERIALIZABLE(可串行化)
  • REPEATABLE READ (可重复读)
  • READ COMMITED(读提交数据)
  • READ UNCOMMITED(读未提交数据)

数据库的完整性

完整性子系统和完整性规则

定义

完整性:是指数据的正确性、有效性和相容性。

  • 正确性:数据的合法性,e.g. 数值类型中只含数字,不含字母。
  • 有效性:数据是否属于定义的有效范围。
  • 相容性:同一事实的两个数据应相同。

完整性约束条件(完整性规则):为保证数据的完整性而规定的条件。

完整性检查:检查 DB 中数据是否满足完整性约束条件。

完整性子系统:DBMS 中执行完整性检查的子系统。其功能有:

  • 监督事务的执行,测试其是否违反完整性约束条件;
  • 若有违反,则按进行预定的处理。
完整性规则的组成

每个规则包括三部分:

  • 触发条件:规定何时执行本规则进行检查;
  • 约束条件:又称谓词,定义应满足的条件;
  • 否则子句:规定不满足条件时该作的处理。

在关系 DB 中,完整性规则可分为三类:

  • 域完整性规则:定义属性取值范围。
  • 域联系的规则:定义属性间的联系、影响和约束。
  • 关系完整性规则:定义更新操作对值的影响和限制。

完整性规则用 DDL 描述,由系统执行检查。

SQL 中的完整性约束

完整性约束分为三大类:

  • 域约束
  • 基本表约束
  • 断言
域约束

定义属性的取值范围——属性值约束。

包括:域约束子句非空值约束基于属性的检查子句

1
2
3
CREATE DOMAIN COLOR CHAR(6) DEFAULT '???'	# 若插入COLOR不再范围内,则置为???
	CONSTRAINT VALID_COLORS	                # 域约束名
		CHECK(VALUE IN ('RED', 'YELLOW', 'BLUE', 'GREENN', '???'))

允许域约束上的 CHECK 子句可以有任意复杂的条件表达式

image-20220516223852029 image-20220516223859244
基本表约束

都可以加 CONSTRAINT 约束名 # 指定域约束名

候选键约束(主键约束)

可用候选键约束约束来描述实体完整性规则。

1
2
UNIQUE(<列名序列>)      # 候选键定义,仅表示唯一,非空需要加 NOT NULL
PRIMARY KEY(<列名序列>)	# 主键定义,仅有一个,默认非空。

其实有两种定义主键的方法,一种是在属性后增加关键字,另一种是在属性表中加入额外的定义主键的子句(主键子句和主键短语)

外键约束

1
2
3
4
FOREIGN  KEY(<列名序列1>).
   REFERENCES  <参照表>  [(<列名序列2>)]
   [ ON  DELETE <参照动作> ]
   [ ON  UPDATE <参照动作> ]

作为主键的关系叫参照表,作为外键的关系叫依赖表

外部码的取值只有两种情况:

  1. 取空值;
  2. 取参照关系中的主码值。

当用户的删除或修改操作违反了上述规则时,如何保持此种约束呢?SQL 中提供了五种可选方案供数据库实现者使用:

  • NO ACTION(无影响)
  • CASCADE(级联方式)
  • RESTRICT(受限方式)
  • SET NULL(置空值)
  • SET DEFAULT(置缺省值)

检查约束

对单个关系的元组值加以约束。

对表内元组说明约束时,在 CREATE TABLE 语句中的属性表、主码、外部码的说明之后加上 CHECK 子句。

每当对元组进行插入或修改操作时,都要对 CHECK 子句的条件表达式求值,如果条件为假,违背了约束,系统将拒绝该插入或修改操作。

CHECK 子句的一般格式为: CHECK <条件>

1
CHECK (weight >= 80 and (color = 'red' and weight <= 200) or (color != 'red' and weight <= 400))
断言

复杂情况下用

如果完整性约束与多个关系有关,或者与聚合操作有关,SQL 提供 “断言”(Assertions)机制让用户书写完整性约束。

定义:

1
CREATE ASSERTION 断言名 CHECK(条件)

撤消:

1
DROP ASSERTION 断言名
image-20220516224400263 image-20220516224612538 image-20220516224414554 image-20220516224425631

断言也可以在关系定义中用检查子句形式定义,但是检查子句不一定能保证完整性约束彻底实现,而断言能保证不出差错。

SQL3 的触发器

定义

  • 触发器(Trigger)不仅能实现完整性规则,而且能保证一些较复杂业务规则的实施。
  • 所谓触发器就是一类由事件驱动的特殊过程,一旦由某个用户定义,任何用户对该触发器指定的数据进行增、删或改操作时,系统将自动激活相应的触发器,在核心层进行集中的完整性控制。

触发器结构分三部分

  • 事件:对数据库的插入、删除和修改等操作。
  • 条件:触发器将测试条件是否成立。
  • 动作:如果测试满足预定的条件,就由 DBM S 执行这些动作。

触发器结构组成

触发事件包括表中行的插入、删除和修改,即执行 INSERT、DELETE、UPDATE 语句

在修改操作(UPDATE)中,还可以指定,特定的属性或属性组的修改为触发条件。

事件的触发还有两个相关的时间:Before 和 After。Before 触发器是在事件发生之前触发,After 触发器是在事件发生之后触发。

触发动作实际上是一系列 SQL 语句,可以有两种方式:

  1. 对被事件影响的每一行(FOR EACH ROW)——每一元组执行触发过程,称为行级触发器。
  2. 对整个事件只执行一次触发过程(FOR EACH STATEMENT)称为语句级触发器。该方式是触发器的默认方式。所以综合触发时间和触发方式,触发器的基本类型如下表所示。
image-20220517153502055
实例
image-20220517153550774 image-20220517153613756 image-20220517153620490 image-20220517153626559
image-20220517160117909 image-20220517153714566 image-20220517160156102

SQL Server 的数据库完整性及实现方法

SQL Server 具有较健全的数据库完整性控制机制。

SQL Server 使用约束、缺省,规则和触发器 4 种方法

定义和实施数据库完整性功能。

数据库的安全性

安全性 vs 完整性:前者,非法,蓄意;后者,合法,无意

定义:是指保护 DB,防止不合法的使用,以免数据的泄漏、非法更改和破坏。

安全性级别

环境级、职员级、OS 级、网络级、DBS 级

这里只讨论 DBS 级的安全性问题。

权限

定义:用户使用数据库的方式。

内容

  • 访问 DB 的权限:读 ,插入,修改,删除 权限

  • 修改 DB 的权限:索引,资源(创建新关系),修改,撤销 权限

方式

  • 授权:可根据需要把在某对象上的某些权限授予特定的用户。
  • 转授:若拥有转授权,则允许把已获得的权限再转授给其他用户。
  • 回收:也可以撤消已授给某用户的某些权限

安全性和授权

安全性由两个机制提供:视图授权子系统

1
2
3
4
5
6
7
GRANT <权限表> ON <数据库元素>
          TO<用户名表>
         [ WITH GRANT OPTION

# 所有权限:ALL PRIVILEGES
# 数据库元素:关系,视图,域(域名前加 DOMAIN
# WITH GRANT OPTION: 可以传递权限
1
2
3
4
5
REVOKE <权限表> ON <数据库元素>
         FROM<用户名表>
         [ RESTRICT|CASCADE ] # 回收权限
         
REVOKE GRANT OPTION FOR ... # 回收转授出去的转让权限

数据加密

定义:数据存储和传输时采用加密技术

数据加、 解密的代价也不小。 因此,DBMS 往往把加密特性作为一种可选功能,由用户决定是否选用。 如果选用了加密功能,用户必须要保管好自己的加密密钥和解密密钥,不能失去或泄露。

数据的安全性和完整性是两个不同的概念。

数据的安全性是防止数据库被恶意破坏和非法存取,而数据完整性是为了防止错误信息的输入,保证数据库中的数据符合应用环境的语义要求。

安全性措施的防范对象是非法用户和非法操作,而完整性措施的防范对象是不合语义的数据。

自然环境的安全性

DBS 的设备、硬件和环境的安全性

对象关系数据库

DB 技术发展过程

数据模型的演变过程

  • 平面关系模型:属性不可分,都是基本数据类型
  • 嵌套关系模型:属性可以是基本数据类型,也可以是关系类型(表),且数据结构可以多次嵌套。
  • 复合对象模型:属性可以是基本数据类型,也可以是关系类型,还可以是元组类型,且数据结构可以多次嵌套。
  • 面向对象模型:在复合对象模型的基础上,数据结构的嵌套采用引用(指针)方式,并且引入面向对象技术的继承性等概念。

查询语言的演变

主要指 SELECT 语句的演变过程

  • RDB (关系型数据库) 中的 SELECT 语句:由六个子句构成

  • ORDB (面向关系型数据库) 中的 SELECT 语句 (SQL3 标准):引入了路径表达式、嵌套与解除嵌套等概念。

  • OODB (面向对象型数据库) 中的 SELECT 语句 (ODMG 标准 OQL):有了更多的扩充,并与宿主语言语句混合起来,可以表达更为复杂的查询操作。

概念建模的演变

  • ER 图:主要用于关系数据库的设计

  • 对象联系图:它是 ER 图的扩充,使之能表达对象之间的引用

  • UML 的类图:是一种纯 OO 技术的结构,体现了现实世界数据之间面向对象的各种联系方式。

image-20220529134938840

对象联系图

三种模型的表示

集合是类,元组是对象

image-20220529135236469 image-20220529135401326

嵌套的关系结构描述

定义 Dept(dno,dname,staff(empno,ename,age)) 的嵌套关系

方法 1:类型

1
2
3
4
type DeptRel = relation(dno:integer, dname:string, staff:EmpRel);	# 定义车间类型
type EmpRel = relation(empno:integer, ename:string, age:integer);	# 定义职员类型

persistent var Dept:DeptRel # 持久变量形式说明

方法 2:先元组,再类型

1
2
3
4
5
6
7
type DeptTup = tuple(dno:integer, dname:string, staff:EmpRel);	# 定义车间元组
type EmpTup = tuple(empno:integer, ename:string, age:integer);	# 定义职员元组

type DeptRel = set(DeptTup);	# 定义车间类型(元组的集合)
type EmpRel = set(EmpTup);

persistent var Dept:DeptRel

方法 3:元组 + 集合 set

1
2
3
4
type DeptTup = tuple(dno:integer, dname:string, staff:set(EmpTup));
type EmpTup = tuple(empno:integer, ename:string, age:integer);

persistent var Dept:set(DeptTup);

引用类型

嵌套关系和符合对象无法表达递归结构

以下的类型构造不合法:

image-20220529140813875

可以采用引用技术解决类型定义中的递归问题。利用指针(对象标识),指向关系。

image-20220529140850536

对象联系图的成分

名称符号含义
椭圆对象 / 实体
小圆圈$\bigcirc$基本数据类型(整型、实型、字符串型)属性
椭圆间的边“引用”
单箭头$\rightarrow$单值属性
双箭头$\rightarrow\rightarrow$多值属性
双线箭头$\Rightarrow$子类 $\Rightarrow$ 超类
双向箭头$\longleftrightarrow$两属性间的逆联系

https://markdown-1303167219.cos.ap-shanghai.myqcloud.com/Snipaste_2022-06-01_21-20-55.png

数据的泛化 / 细化

数据的泛化 / 细化:对概念之间联系进行抽象的一种方法

  1. 超类是子类的泛化,子类是超类的细化。
  2. 超类型:较高层的对象;子类型:较低层的对象。具有继承性。
  3. 泛化 / 细化联系:泛化边 (双线箭头);泛化边:子类 $\Rightarrow$超类。
image-20220529141729308

面向对象的数据类型

基本类型

整型,浮点型,字符,字符串,布尔型,枚举型。

复合类型

类型类型顺序重复性元素个数例子
行 / 元组 / 结构 / 对象类型不同有序日期 (1,October,2007)
数组类型相同有序可重复预置[1,2,1] $\ne$ [2,1,1]
列表类型相同有序可重复未预置{1,2,1} $\ne$ {2,1,1}
包 / 多集类型相同无序可重复未预置{1,2,1} = {2,1,1}
集合 / 关系类型相同无序不可重复未预置{1,2} = {2,1}

后四行统称 “聚集类型”;数据类型可以嵌套。

引用类型

数据类型的定义只能嵌套,若要允许递归,就要前面提到的引用类型 。

ORDB 的定义语言

ORDB

  • 对象关系数据模型 (ORDB):在传统的关系数据模型基础上,提供元组、数组、集合一类丰富的数据类型以及处理新的数据类型操作的能力,并且有继承性和对象标识等面向对象特点。

  • 对象关系数据库系统:基于对象关系数据模型的 DBS。

数据类型

复合类型有下列四种:

  1. 结构类型:不同类型元素的有序集合称为结构。
  2. 数组类型:同类元素的有序集合,称为数组(array)。
  3. 多集类型:同类元素的无序集合(有的成员可多次出现),称为多集(multiset)。
  4. 集合类型:同类元素的无序集合(每个成员只能出现一次),称为集合(set)。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
CREATE TYPE MyString char varying;			    /*定义变长字符串类型*/

CREATE TYPE DATE(day integer, month char(10), year integer);	/*定义结构类型*/
CREATE TYPE NameArray MyString[10];			    /*定义数组类型*/
CREATE TYPE	StudentGrade multiset(integer);		/*定义包/多集类型*/
CREATE TYPE CourseList setof(MyString);			/*定义集合类型*/

/*使用中间变量,建立表类型*/
CREATE TYPE CourseGrade (course MyString, grade integer)
CREATE TYPE StudentCourse (name MyString, cg setof(CourseGrade)); /*定义嵌套类型*/
CREATE TABLE sc of Type StudentCourse;

/*不使用中间变量,建立表类型*/
CREATE TABLE sc(name MyString, cg setof(course MyString, grade integer));

继承性

继承性可以发生在类型一级或表一级。

类型级的继承性

数据类型之间的子类型与超类型的联系

1
2
3
4
5
6
7
/*超类型*/
CREATE TYPE Person(name MyString, social_number integer);
/*子类型*/
CREATE TYPE Student(degree MyString, department MyString)
 					under Person;
CREATE TYPE Teacher(salary integer,department MyString
                    under Person;
image-20220529143216215
表级的继承性

在表级实现继承性(子表与超表的联系)

1
2
3
4
5
6
7
/*超表*/
CREATE TABLE People(name MyString, social_number integer);
/*子表*/
CREATE TABLE Students(degree MyString, department MyString)
 					under People;
CREATE TABLE Teachers(salary integer,department MyString
                    under People;
image-20220529143306666

子表和超表应满足下列两个一致性要求

  1. 超表中每个元组最多可以与每个子表中的一个元组对应。
  2. 子表中每个元组在超表中恰有一个元组对应,并在继承的属性上有相同的值。

引用类型

在嵌套引用时,不是引用对象本身的值,是引用对象标识符(即 “指针” 的概念)

利用 ref (表名) 表示引用类型,即地址。以此实现递归。若集合类型,需加 setof()

1
2
3
CREATE TYPE MyString char varying;
CREATE TABLE dpept(dno integer, dname MyString, staff setof(ref(emp)));
CREATE TABLE emp(empno integer, ename MyString, age integer, works_for setof(ref(dept)));

ORDB 的查询语言

SELECT 语句

扩充 SQL 对 SELECT 语句的使用规定

  1. 允许用于计算关系的表达式出现在任何关系名可以出现的地方。

  2. 每个基本表设置一个元组变量,然后才可引用

    • 在 FROM 子句中要为每个关系定义一个元组变量。
    • 如:e.g. FROM university as U
  3. 当属性值为单值或结构值时,属性的引用方式仍和传统的关系模型一样,在层次之间加点 .

    • university 的 president 属性,只有一个 faculty 元组与之对应。
    • **U.president.fname √ **
  4. 当路径中某个属性值为集合时,就不能连着写下去, 必须定义元组变量。

    • university 的 staff 属性,有多个 faculty 元组与之对应,不能直接获取属性值。
    • U.staff.frame ×
image-20220529144911788

sap PPT 就到这里了

嵌套与解除嵌套

例:检索使用本校教材开课的教师工号、姓名及所在学校:

“接触嵌套”:将一个嵌套关系转换成 1NF 的过程。

1
2
3
SELECT  A.unameB.fnoB.fname
FROM  university as AA.staff as  BB.teach  as  C
WHERE  C.editor.uname = A.uname;

“嵌套”:将一个 1NF 关系转化为嵌套关系。

1
2
3
4
5
/* 利用set 和 group by 实现嵌套*/
SELECT  A.unameset(B.fnoB.fname) as teachers	
FROM university as A, A.staff as B, B.teach as C
WHERE C.editor.uname = A.uname
GROUP BY A.uname

函数的定义和使用

1
2
3
4
5
6
7
8
9
/*定义类型 和 表*/
CREATE TYPE StudentCourseGrade(name MyString, cg setof(course MyString, grade integer));
CREATE TABLE sc of TYPE StudentCourseGrade

/*定义函数*/
CREATE FUNCTION course_count(one_student StudentCourseGrade) /*参数类型:Student CourseGrade*/
RETURNS integer AS	/*返回值*/
SELECT count(B.cg)
FROM one_student as B

复合值的创建和查询

INSERT 复合值

1
INSERT INTO sc VALUES ('ZHANG', set(('DB',80),('OS',85)));

SELECT 复合值

1
2
3
4
5
/*检索 WANG LIU ZHANG三位学生选修的课程门数 */
SELECT A.name, count(A.cg)
FROM sc as A 
WHERE A.name IN set('WANG','LIU','ZHANG')
GROUP BY A.name