这里参考了参考学习了博主:轻松的小希
在此表示感谢
第一章 数据库概论
1.1 数据库系统概念
1.1.1 数据库的四个概论
数据、数据库、数据库管理系统、数据库系统
1.1.2 数据库系统的特点
1.2 数据库数据模型
1.2.1 数据模型的概
1.2.2 数据模型要求
1.2.3 数据模型分类:概念模型(通常E_R图表示)、逻辑模型(现主流关系型)、物理模型
1.2.4 概念模型的概述:E_R图、实体、属性、码、域、实体集、联系(一对一、一对多、多对多)
1.2.5 数据模型的组成:数据结构、数据操作、数据完整性约束
1.2.6 常见逻辑模型:层次模型、网状模型、关系模型(关系-表)、面向对象数据模型、对象关系数据模型
1.3 数据库系统结构
1.3.1 数据库系统的模式概念
1.3.2 数据库系统的三级模式结构
1.3.3 数据库系统的二级映射功能
1.4 数据库系统的组成
第二章 关系数据库
2.1 关系概论
2.1.1 关系
2.1.2 关系模式
2.1.3 关系数据库
2.1.4 关系模型的存储结构
2.2 关系操作
2.3 关系完整性
实体完整性
参照完整性
用户定义完整性
第三章 SQL语言
3.1 SQL的概述
3.2 SQL的发展
3.3 SQL的特点
3.4 SQL的功能
3.5 SQL的结构
3.6 SQL的数据类型
3.7 数据定义语言(DDL)
3.7.1 模式
3.7.1.1 模式的定义
3.7.1.2 模式的删除
3.7.2 基本表
3.7.2.1 基本表的定义
3.7.2.2 基本表的修改
3.7.2.3 基本表的删除
3.7.3 视图
3.7.3.1 视图的定义
3.7.3.2 视图的修改
3.7.3.3 视图的删除
3.7.4 索引
3.7.4.1 索引的定义
3.7.4.2 索引的修改
3.7.4.3 索引的删除
3.8 数据库查询语言(DQL)
3.8.1 单表查询
3.8.1.1 简单查询
3.8.1.2 条件查询
3.8.1.3 IN子句查询
3.8.1.4 模糊查询
3.8.1.5 空值查询
3.8.1.6 与或查询
3.8.1.7 排序查询
3.8.1.8 聚合查询
3.8.1.9 分组查询
3.8.1.10 过滤查询
3.8.2 连接查询
3.8.2.1 等值查询
3.8.2.2 非等值查询
3.8.2.3 自身连接查询
3.8.2.4 外连接查询
3.8.2.5 多表连接
3.8.3 嵌套查询
3.8.3.1 带有比较运算符的子查询
3.8.3.2 带有IN谓词的子查询
3.8.3.3 带有ANY或ALL谓词的子查询
3.8.3.4 带有EXISTS谓语的子查询
3.8.4 集合查询
3.8.4.1 并操作UNION
3.8.4.2 交操作INTERSECT
3.8.4.3 差操作EXCEPT
3.8.5 派生表查询
3.9 数据操作语言(DML)
3.9.1 插入
3.9.1.1 插入一条数据
3.9.1.2 插入多条数据
3.9.1.3 带子查询的插入
3.9.2 修改
3.9.2.1 修改一条数据
3.9.2.2 修改多条数据
3.9.2.3 带子查询的修改
3.9.3 删除
3.9.3.1 删除一条数据
3.9.3.2 删除多条数据
3.9.3.3 带子查询的删除
第四章 数据库安全性
4.1 数据库安全性概述
4.1.1 不安全因素
4.1.2 安全标准
4.2 数据库安全性控制
4.2.1 用户身份鉴别
4.2.2 存取控制机制
4.2.3 权限授权回收
第五章 数据库完整性
5.1 实体完整性
5.2 参照完整性
5.3 用户定义完整性
5.4 触发器
5.4.1 定义触发器
5.4.1 删除触发器
第六章 关系数据库理论
6.1 依赖
6.1.1 函数依赖
6.1.2 平凡函数依赖
6.1.3 非平凡函数依赖
6.1.4 完全函数依赖
6.1.5 部分函数依赖
6.1.6 传递函数依赖
6.2 码
6.3 范式
6.3.1 1NF
6.3.2 2NF
6.3.3 3NF
6.3.4 BCBF
第七章 数据库恢复技术
7.2
第一章 数据库概论
1.1 数据库系统概念
1.1.1 数据库的四个概论
- 数据(data):数据是数据库中存储的基本对象,它是表述事物的符号记录。
- 数据库(database): 数据库是长期存储在计算机内、有组织的、可共享的大量数据的集合,也称为数据仓或数据库仓库。
- 数据库管理系统(DBMS):数据库管理系统是位于用户与操作系统之间的数据管理软件,它是一个大型复杂的软件系统,主要用于科学地组织和存储数据、高效获取和维护数据。
- 数据库系统(DBS): 数据库系统主要是由数据库、数据库管理系统(及开发工具)、数据库管理员以及应用程序所构成的一套人机系统。
1.1.2 数据库系统的特点
- 数据的整体结构化
数据的整体结构化是数据库的主要特征之一,它不再仅仅针对某一个应用,不仅数据内部结构化,整体也是结构化的,数据直接具有联系,数据记录可以变长,数据的最小存取单位是数据项。
- 数据的共享性高,冗余度低且易扩充
数据面向整个系统,可以被多个用户、多个应用共享使用
由此带来的优点:减少数据冗余,节约存储空间;避免数据之间的不相容性以及不一致性;使系统易于扩充。
- 数据独立性高
数据独立性由数据库管理系统的二级映射保证实现,主要分为:物理独立性和逻辑独立性。
物理独立性:指用户的用户程序与数据库中的数据的物理存储是相互独立,当数据的物理存储改变时,应用程序不用改变。
逻辑独立性:指用户的应用程序与数据库中数据的逻辑结构是相互独立的,当数据的逻辑结构改变时,应该程序不用改变。
- 数据由数据库管理系统统一管理和控制
数据库管理系统提供的数据控制功能:
- 数据的安全性(Security)保护:保护数据以不合法的使用造成数据的泄密和破坏。
- 数据的完整性(Integrity)检查:保证数据的正确性、有效性和相容性。
- 并发(Concurrency)控制:对多个用户的并发操作加以控制和协调,防止相互干扰而得到错误的结果。
- 数据库修复(Recovery)技术:将数据库从错误状态恢复到某一已知正确状态。
1.2 数据库数据模型
1.2.1 数据模型的概
数据模型是对现实世界数据特征的抽象,通俗地讲数据模型就是现实世界的模拟,数据模型是数据库系统的核心和基础。
1.2.2 数据模型要求
- 比较能真实模拟现实世界
- 容易为人所理解
- 便于计算机上实现
1.2.3 数据模型分类:
概念模型(通常E_R图表示):概念模型也称信息模型,它是按照用户的观点来对数据和信息建模,用于数据库设计。
逻辑模型(现主流关系模型): 逻辑模型主要包括层次模型、网状模型、关系模型、面向对象数据模型等模型,按照计算机系统的观点对数据建模,由DBMS实现。
物理模型:物理模型是对数据最底层的抽象,描述数据在系统内部的表示方式和存取方式,在磁盘或磁带上的存取方式和存取方法。
1.2.4 概念模型的概述
- 概念模型的用途
- 概念模型用于信息时间的建模
- 是现实世界到机器世界的一个中间层。
- 是数据库设计的有力工具
- 数据库设计人员和用户之间交流的语言
- 概念模型的要求
- 较强的语义表达能力
- 简单、清晰、易于用户理解
- 概念模型的表示
实体-联系方法,用E-R图来描述现实世界的概念模型,E-R方法也称为E-R模型。 - 信息世界中的基本概念
实体(Entity): 客观存在并可相互区别的事物称为实体。
属性(Attribute): 实体所具有的某一特征称为属性。一个实体可以由若干个属性来描述。例如学生实体可以由学号、姓名、性别、出生年份等属性组成。
码(Key): 唯一标识实体的属性集称为码。
域(Domain): 属性的取值范围称为该属性的域。
**实体型(Entiry Type):**具有相同属性的实体必然具有共同的特征和性质。用实体名及其属性名集合来抽象和刻画同类实体,称为实体型。例如,学生(学号,姓名,性别,出生年份,系,入学时间)就是一个实体型。
实体集(Entity Set): 同型实体的集合称为实体集,例如,全体学生就是一个实体集。
联系(Relationship): 在现实世界中,事物内部以及事物之间是有联系的,这些联系在信息世界中反映为实体型内部的联系和实体(型)之间的联系,实体内部的联系通常是指组成实体的各属性之间的联系。实体之间的联系通常是指不不同实体集之间的联系 - 两个实体型之间的联系
- 一对一(1:1)
如果对于实体集A中的每一个实体,实体集B中至多有一个(也可以没有)实体与之联系,反之亦然。 - 一对多(1:n)
如果对于实体集A中的存在一个实体,与实体集B中n个实体(n>1)与之联系,反之,对于实体集B中的每一个实体,实体集A中至多只有一个实体与之联系,则称实体集A与实体集B有一对多联系,记为1:n。 - 多对多(n:n)
如果对于实体集A中的存在一个实体,实体集B中有n个实体(n>1)与之联系,反之亦然,则实体集A与实体集B具有多对多联系,记为n:m。
- 一对一(1:1)
1.2.5 数据模型的组成:
数据结构
描述数据库的组成对象,以及对象之间的联系,它是对系统静态特性的描述。
数据操作
对数据库中个对象(型)的实例(值)允许执行的操作的集合,包括操作及有关操作规则,它是对系统动态特性的描述。
操作类型包括:查询、更新(包括插入、删除、修改)
数据完整性约束条件
是一组完整性规则的集合,用以限定符合数据模型的数据库状态以及状态变化,以保证数据的正确性、有效和相容。
完整性规则:给定的数据库模型中数据及其所具有的制约和依存规则。
1.2.6 常见逻辑模型:
这里只对模型进行简单介绍,重点介绍关系模型,其他模型做一个简单了解即可。
层次模型、网状模型、关系模型(关系-表)、面向对象数据模型、对象关系数据模型
1.2.7 层次模型
定义:层次数据模型是用树状结构来组织数据的数据模型。
1.2.8 网状模型
定义:用有向图表示实体和实体之间的联系的数据结构模型称为网状数据模型。
1.2.9 关系模型
定义:使用表格表示实体和实体之间的关系的数据模型称之为关系数据模型。既使用二维表表示实体和实体之间的联系(实体与实体之间的联系也使用二维表表示)。
1.3 数据库系统结构
从数据库应用开发人员角度看,数据库系统通常采用三级模式结构,是数据库系统内部的系统结构。
1.3.1 数据库系统的模式概念
- 模式(Schema)
数据库逻辑结构和特征的描述
是型的描述,不涉及具体值
反映的数据的结构及其联系
模式时相对稳定的 - 实例(Instance)
模式的一个具体值
反映数据库某一时刻的状态
同一个模式可以有很多个实例
实例随数据库中的数据的更新而变动
1.3.2 数据库系统的三级模式结构
三级模式结构说明:
模式:
模式(也称为逻辑模式)
数据库中全体数据的逻辑结构和特征的描述。(所有用户的数据表)
外模式:
外模式(也称子模式或用户模式)
数据库用户(包括应用程序员和最终用户)使用局部数据的逻辑结构和特征的描述
数据库用户的数据视图
内模式:
内模式(也称存储模式)
是数据物理结构和存储方式的描述
是数据在数据库内部的表示方式
记录的存储方式(例如,顺序存储、B树结构存储、hash方式存储等)
索引的组织方式。
数据是否压缩存储
数据是否加密
数据存储记录结构的规定
1.3.3 数据库系统的二级映射功能
- 外模式-模式 映像
保证数据的逻辑独立性
(1)当模式改变时,数据库管理员对外模式-模式映像作相应改变,使外模式保持不变。
(2)当引用程序是依据数据的外模式编写的,应用程序不必修改,保证了数据与程序的逻辑独立性。
- 模式-内模式 映像
保证数据的物理独立性
(1)当数据库的存储结构变了(例如选择了另一种存储结构),数据库管理员修改模式-内模式映像,使模式保持不变。
(2)应用程序不受影响,保证了数据与程序的物理独立性。
1.4 数据库系统的组成
- 数据库
- 数据库管理系统(及开发工具)
- 数据库管理员
- 应用程序
第二章 关系数据库
2.1 关系概论
2.1.1 关系
实现世界的实体以及实体间的各种联系均用关系(二维表)来表示。
笛卡尔积(Cartesian Product):给定一组域D1,D2,…,Dn,允许其中某些域是相同的。D1,D2,…,Dn的笛卡尔积为:D1xD2x…xDn={(d1,d2,… ,dn) | di∈Di,i=1,2,…,n},笛卡尔积是所有域的所有值的一个组合,它不能重复。
- 元组(Tuple):笛卡尔积中的每一个元素(d1,d2,…,dn)叫作一个n元组或简称元组。
- 分量(Component):笛卡尔积中每一个元素(d1,d2,…,dn)中的每一个值di叫作一个分量。
关系(Relation):D1×D2×…×Dn的子集叫作在域D1,D2,…,Dn上的关系,表示为R(D1,D2,…,Dn),其中,R为关系名,n为关系的目或度(Degree)。关系中的每个元素是关系中的元组,通常用t表示。当n=1时,称该关系为单元关系(Unary relation)或一元关系 ,当n=2时,称该关系为二元关系(Binary relation),关系也是一个二维表,表的每行对应一个元组,表的每列对应一个域,关系中不同列可以对应相同的域,为了加以区分,必须对每列起一个名字,称为属性(Attribute),n目关系必有n个属性。若关系中的某一属性组的值能唯一地标识一个元组,则称该属性组为候选码,简单的情况:候选码只包含一个属性,最极端的情况:关系模式的所有属性组是这个关系模式的候选码,称为全码(All-key),若一个关系有多个候选码,则选定其中一个为主码(Primary key),候选码的诸属性称为主属性(Prime attribute),不包含在任何侯选码中的属性称为非主属性(Non-Prime attribute)或非码属性(Non-key attribute) 。
- 三类关系:
- 基本关系:实际存在的表,是实际存储数据的逻辑表示。
- 视图表:由基本表或其他视图表导出的表,是虚表,不对应实际存储是数据。
- 查询表:SQL语句查询出来的结果显示出来的表。
- 基本关系的性质:
- 列是同质的
- 不同的列可出自同一个域,其中的每一个列称为一个属性,不同的属性要给予不同的属性名。
- 列的顺序无所谓,列的次序可以任意交换
- 行的顺序无所谓,行的次序可以任意交换
- 任意两个元组的候选码不能相同
- 分量必须取原子值,这是规范条件中最基本的一条。
2.1.2 关系模式
关系模式:关系模式是对关系的描述。如元组集合的结构,完整性约束条件。
关系模式的表示方式:R(U,D,DOM,F)
R 关系名
U 组成该关系的属性名集合
D U中属性所来自的域
DOM 属性向域的映像集合
F 属性间数据的依赖关系的集合
关系模式通常可以简记为R(U)
关系模式与关系:
关系模式是型,而关系是值,关系模式和关系往往统称为关系。
关系模式是关系的描述,是静态的、稳定的。
关系则表示关系模式在某一时刻状态或内容,是动态的,随时间不断变化的。
2.1.3 关系数据库
关系数据库:在一个给定的应用领域中,所有关系的集合构成一个关系数据库。
关系数据库的型与值:
- 关系数据库的型:关系数据库模式,是对关系数据库的描述。
- 关系数据库的值:关系模式在某一个时刻对应的关系集合,通常称为关系数据库。
2.1.4 关系模型的存储结构
关系数据库的物理组织:
- 有的关系数据库管理系统中一个表对应一个操作系统文件,将物理数据组织交给操作系统完成。
- 有的关系数据库管理系统从操作系统那里申请若干个大文件,自己划分文件空间,组织表、索引等存储结构,并进行存储管理。
2.2 关系操作
常用关系操作:
- 查询操作:选择、投影、连接、除、并、差、交、笛卡尔积
- 数据更新:插入、删除、修改
关系操作特点:操作的对象和结果都是集合。
2.3 关系完整性
关系的完整性约束:
- 实体完整性约束:实体完整性通过表的主键来实现。
- 参照完整性约束:通过定义一张表中外键与另一张表中主键之间的引用规则来约束这两张表之间的联系。
- 用户定义的完整性:该属性值的特定约束。比如非空、只能是给定的选择范围值(如男女,大于18等)。
第三章 SQL语言
3.1 SQL的概述
SQL(structured Query Language)结构化查询语句,是关系型数据库的标准语言,SQL是一个通用的、功能极强的关系数
据库语言。
3.2 SQL的发展
1986年发布第一个版本:SQL/86
目前,没有任何一个关系型数据库系统能支持所有标准的概念和特性
3.3 SQL的特点
- 综合统一
- 高度非过程化
- 面向结合的操作方式
- 以同一种语法结构提供两种使用方式,SQL语言既是自含式设计语言,又是嵌入式语言
- 语言简洁,易学易用
3.4 SQL的功能
SQL功能 | 关键词 |
---|---|
DDL | create,drop,alter |
DML | insert,update,delete |
DQL | select |
DCL | grant,revoke |
3.5 SQL的结构
SQL支持关系型数据库的三级模式结构:
3.6 SQL的数据类型
数据类型 | 含义 |
---|---|
char(n),character(n) | 长度为n个字节的定长字符串 |
varchar(n),charactervarying(n) | 最大长度为n个字节的变长字符串 |
CLOB | 字符串大对象 |
BLOB | 二进制大对象 |
int,integer | 长整数(4字节) |
smallint | 短整数(2字节) |
bigint | 大整数(8字节) |
numeric(p,d), decimal(p,d),DEC(p,d) | 定点数,由p位数字(不包括符号、小数点)组成,小数点后面又d位数 |
real | 取决于机器精度的单精度浮点数 |
double precision | 取决于机器精度的双精度浮点数 |
float(n) | 可选精度的浮点数,精度至少为n位数 |
boolean | 逻辑布尔量 |
date | 日期,包含年、月、日,格式为YYYY-MMDD |
time | 时间,包含一日的时、分、秒,格式为HH-MM-SS |
timetamp | 时间戳类型 |
interval | 时间间隔类型 |
3.7 数据定义语言DDL
一个关系数据库管理系统的实例(instance)中可以建立多个数据库,一个数据库可以建立多个模式,一个模式下通常包含多个表、视图和索引等数据库对象。因此SQL的数据定义功能包括定义模式、定义表、定义视图和定义索引。视图式基于基本表的虚表,索引式依附于基本表, 因此SQL通常不提供修改视图定义和修改索引定义的操作。用户如果想修改视图或修改索引定义,只能先将原来的视图或索引删除,然后重新定义。不过也有存在提供修改视图或索引语句的关系型数据库管理软件。
表:SQL数据定义语句
操作对象也 | 创建 | 删除 | 修改 |
---|---|---|---|
模式 | create schema | drop schema | – |
表 | create table | drop table | alter table |
视图 | create view | drop view | – |
索引 | create index | drop index | – |
3.7.1 模式
3.7.1.1 模式定义
定义模式实际上是定义了一个命名空间,在这个空间中可以定义该模式包含的数据库对象,如基本表、视图、索引等。
语法格式:
create schema <模式名> authorization <用户名> [<表定义子句>|<视图定义子句>|<授权定义子句>];
实例:为用户Tom 创建一个模式TEST,并且在其中定义一个表Student。
create schema TEST authorization Tom create table Student(
number int,
name varchar(20),
age int);
3.7.1.2 模式的删除
语法格式:
drop schema <模式名> <cascade|restrict>;
cascade:级联,删除模式等同时把该模式中的所有的数据库对象全部删除。
restrict:限制,如果该模式中定义了下属的数据库对象(如基本表、视图、索引等),数据库管理系统拒绝该条删除模式等语句执行,仅当该模式中没有任何下属对象时才能被执行。
实例:删除模式TEST,同时将该模式中的Student表一起删除。
drop schema TEST cascade;
3.7.2 基本表
3.7.2.1 基本表定义
建立数据库最重要的一步就是定义一些基本表,SQL语言使用create table关键字进行基本定义。
语法格式:
create table <表名> (
<列名> <数据类型> [<列级完整性约束条件>]
[,<列名><数据类型>[<列级完整性约束条件>]
……
[, <表级完整性约束条件>]
);
实例1:创建一个学生表Student,学号是主码,姓名取值唯一。
先创建一个模式:
create schema T-S authorization Tom;
create table Student(
Sno char(9) primary key,
Sname char(20) unique,
Ssex char(2),
Sage smallint,
Sdept char(20)
);
实例2:创建一个课程表Course,课程号是主码。
create table Course(
Cno char(4) primary key,
Cname char(40),
Cano char(4),
Ccredit int
);
实例3:创建一个学生选课表SC,学生号和课程号组成主码。
create table SC(
Sno char(9);
Cno char(4)
Grade decimal(40,2),
primary key(Sno,Cno),
foreign key(Son) references Student(Sno),
foreign key(Cno) references Course(Cno)
);
** 模式与表**
任何一个表都属于某一个模式,一个模式包含多个基本表,定义基本表所属模式有三种方式:
- 在定义表是显示给出模式名:
create table “S-T”.Student(…);
crate table “S-T”.Cource(…);
create table “S-T”.SC(…); - 在创建模式语句是同时创建表
- 设置所属模式
在数据库管理系统中创建基本表或其他对象时,若没有指定模式,系统会根据搜索路径来确定该对象所属的模式,关系数据库管理系统会使用模式里表中第一个存在的模式作为该数据库对象的模式名,若搜索路径中的模式名不存在,系统将给出错误。
3.7.3.3 基本表的修改
语法格式:
alter table <表名>
[add [column] <新列名> <数据类型> [列级完整性约束条件]]
[add <表级完整性约束条件>]
[drop [column] <列名> [cascade|restrict]]
[drop constraint <完整型约束条件> [cascade|restrict]]
[alter column <列名> <数据类型> ];
实例1:向Student表增加“入学时间”列,其数据类型为日期类型
不管基本表中原来是否有数据,新增加的列一律为空
alter table Student
add S_entrance date;
实例2:将年龄的数据类型字符型(假设原来的数据类型是字符型)改为整数型。
alter table Student
alter column Sage int;
实例3:增加课程名必须取唯一的约束条件
alter table Course
add unique(Cname);
3.7.2.3 基本表的删除
语法格式:
drop talbe <表名> [cascade|restrict];
cascade(级联): 在删除基本表的同时,相关依赖这个表的对象一起删除;
restrict(限制): 在删除基本表时,会验证该表是否别其他对象依赖,若存在其他对象依赖,则删除该表失败
实例:删除Student表
drop table Student cascade;
3.7.3 视图
3.7.3.1 视图的定义
视图是一个虚拟表,其内容查询定义。但视图并不存储数据,视图数据来自定义视图的查询所引用的表。关系数据库管理系统执行create view 语句时只是把视图定义存入数据字典,并不执行其中的select语句。在对视图查询时。视图对重构数据库提供了一定程度的逻辑独立性,能够对机密数据提供安全保护,适当的利用视图可以清晰的表达查询。
语法格式:
create view <视图名> [(<>[,<>]…)] as
<子查询> [with check option];
with check option : 对视图进行update,insert和delete操作时要保证更新、插入或删除的行满足视图定义中的谓词条件(既子查询中的条件表达时)。子查询可以时任意的select语句,是否可以含有order by 子句和distinct短语,则决定具体系统的实现。
实例1: 建立信息系学生的视图
create view IS_Student as
select Sno,Sname,Sage
from Student
where Sdept='IS';
实例2:建立信息系学生的视图,并要求进行修改和插入操作时任需保证该视图只有信息系的学生。
create view IS_Student as
select Sno,Sname,Sage
from Student
where Sdept = 'IS' with check option;
实例2:建立信息系选修1号课程的学生的视图(包括学号,姓名、成绩)。
create view IS_S1(Sno,Sname,Grade) as
select Student.Sno,Sname,Grade
from Student,SC
where Sdept = 'IS' and Student.Sno=SC.Sno and SC.Cno = '1';
实例3:建立信息系选修1号课程且成绩在90分以上的学生视图。
create view IS_S2 as
select Sno,Sname,Grade from IS_S1 where Grade >= 90;
实例4:定义一个反映学生出生年月的视图
create view BT_S(Sno,Sname,Sbirth) as
select Sno,Sname,2021-Sage from Student;
实例5:将学生的学号及平均成绩定义为一个视图。
create view S_G(Sno,Gavg) as
select Sno,AVG(Grade)
from SC group by Sno;
3.7.3.2 视图的删除
drop view <视图名> [cascade];
cascade:如果该视图还有其他视图进行引用,则把这个给视图同时一起删除。
实例1:删除视图BT_S。
drop view BT_S;
3.7.4 索引
3.7.4.1 索引定义
建立索引是加快查询速度的有效手段。(查询过程中数据库实例根据SQL决定是否使用索引查询,用户无法显示指定使用) 用户可以根据需要应用环境的需要,在基本表上建立一个或多个索引,以提供多种存取路径,加快查找速度。一般来说,建立与删除索引有数据库管理员DBA或表的属主负责完成。系统在存取数据是会自动选择适合的索引作为存取路径 用户不必也不能选择索引进行查找。
建立索引原则(同时满足):
- 表记录量比较大的表
- 更改频率较低的表(较少的INSERT、DELETE及对索引对象列的UPDATE操作)
如何建立索引:
在SQL中,建立索引使用create index语句。索引可以建立在该表的一列或多列上,各列之间用逗号分隔。每个列名后面还可以用次序指定索引值的排序次序,可选asc(升)或desc(降),缺省时默认asc。
语法格式:
create [unique] [cluster] index <索引名>
on <表名>(<列名> <次序>[,<列名> <次序>]...);
索引:可以建立在该表的一列或多列上,各列名之间用逗号分隔开。
unique: 此索引的每一个索引值只对应唯一的数据记录
cluster:表示建立的索引是聚簇索引。聚簇索引是指索引顶的顺序与表中记录的物理顺序一致的索引组织。用户可以在最经常查询的列上建立聚簇索引以提高查询效率。显然在一个基本表上最多只能建立一个聚簇索引。建立聚簇索引后,更新索引数据时,往往导致表中记录的物理顺序变更,代价较大,因此对于经常更新的列不宜建立聚簇索引。
实例:为Student,Course,SC三个表建立索引。Student表按学号升序建立唯一索引,Course表按课程号升序建唯一索引,SC表按序号升序和课程好降序建唯一索引。
create unique index Stusno
on Student(Sno);
create unique index Coucno
on Course (Cno);
create unique index Scno
on SC(Sno asc,Cno desc);
3.7.4.2 名称的修改
语法格式:
alter index <旧索引名> rename to <新索引>;
实例:将表SC的SCno索引名改位SCSno。
alter index SCno rename to SCSno;
3.7.4.3 索引的删除
删除索引时,系统会从数据字典中删去有关该索引的描述。
语法格式:
drop index <索引名> on <表名>;
实例:删除Student表的Stusno索引。
drop index Stusno on Student;
3.8 数据查询语言(DQL)
3.8.1 单表查询
语法格式:
select [all|distinct] <目标列表达式>[,<目标列表达式>] ...
from <表名或视图名> [,<表名或视图名>] ... | (select 语句) [as] <别名>
[where <条件表达式>]
[group by <列名1> [having <表达式>]]
[order by <列名2> [asc|desc]];
select子句:指定要显示的属性列
from子句:指定查询对象(基本表、视图、查询子句)
where子句:指定查询条件
group by子句:对查询结果按指定列的值分组。 该属性列值相等的元组为一个组。通常会在每组中作业聚集函数。
having短语:只是group by 子句列,满足指定条件的组才给予输出。
order by 子句:对查询结果表按指定列值升序或降序排序。
常用的查询条件:
查询条件 | 谓词 |
---|---|
比较 | =,>,<,>=,<=,!=,<>,!>,!<,not+上述比较运算符 |
确定范围 | between and,not between and |
确定集合 | in,not in |
字符匹配 | like,not like |
空值 | is null,is not null |
逻辑运算 | and,or,not |
3.8.1.1 简单查询
实例1:查询全体学生学号与姓名。
select Sno,Sname from Student;
实例2:查询全体学生的姓名、学号、所在系。
select Sno,Sname from Student;
实例3:查询全体学生的详细记录。
select * from Student;
实例4:查询全体学生的姓名及出生年份;
select Sname,2022-Sage from Student;
实例5:查询全体学生的名字、出生年份和所在院系,要求小写字母表示系名。
select Sname,'Year of Birth',2022-Sage,LOWER(Sdept) from Student;
3.8.1.2 条件查询
实例1:查询计算机科学系全体学生的名单。
select Sname from Student where Sdept='CS';
实例2:查询所有年龄在20岁以下的学生及其年龄。
select Sname,Sage from Student where Sage<20;
实例3:查询考试成绩有不及格的学生的学号。
select distinct Sno from SC where Grade<60;
实例4:查询年龄在20~23岁(包括20岁到23岁)之间的学生的姓名、系别和年龄。
select Sname,Sdept,Sage from Student where Sage between 20 and 23;
实例5:查询年龄不在20~23岁之间的学生姓名、系别和年龄。
select Sname,Sdept,Sage from Student where Sage not between 20 and 23;
3.8.1.3 IN子句查询
实例1:查询计算机科学系CS、数学系MA和信息系IS学生的姓名和性别。
select Sname,Ssex from Student where Sdept in ('CS','MA','IS');
实例2:查询既不是计算机科学系、数学系,也不是信息系的学生的姓名和性别。
select Sname,Ssex from Student where Sdept not in ('CS','MA','IS');
3.8.1.3 模糊查询
谓词:[not] like ‘<匹配串>’ [escape ‘<转码字符>’]
- %:表示任意长度字符串(长度可为0)
- _:表示任意单个字符(一定要有一个字符)
实例1:查询学号为201215121的学生详细情况。(没有%、_时与“=”等价)。
select * from Student where Sno like '201215121';
select * from Student where Sno = '201215121';
实例2: 查询所有姓刘学生的姓名、学号和性别。
select Sname,Sno,Ssex from Student where Sname like '刘%';
实例3:查询姓“欧阳”且全名为四个汉字的学生的姓名。
select Sname from Student where Sname like '欧阳__';
实例4:查询DB_Design课程的课程号和学分。
使用换码字符将通配符转义为普通字符
select Cno,Ccredit from Course where Cname like 'DB#_Design' escape '#';
实例5:查询以“DB_”开头,并且倒数第三个字符为 i 的的详细情况。
select * from Course where Cname like 'DB#_%i__' escape '#';
3.8.1.5 空值查询
实例1:某些学生选修课程后没有参加考试,所以有选课记录,但没有考试成绩,查询缺少成绩的学生序号和相应的课程号。
select Sno,Cno from SC where Grade is null;
实例2:查询所有有成绩的学生学号和课程号。
select Sno,Cno from SC where Grade is not null;
3.8.1.6 与或查询
实例1:查询计算机系年龄在20岁以下的姓名。
select Sname from Student where Sdept='CS' and Sage<20;
实例2:查询计算机科学系、数学系、信息系学生的姓名和性别。
select Sname,Ssex from Student where Sdept='CS' or Sdept='MA' or Sdept='IS';
3.8.1.7 排序查询
实例1:查询选修了3号课程的学生学号及成绩,查询结果按分数降序排序。
select Sno,Grade from SC where Cno='3' order by desc;
实例2:查询全体学生情况,查询结果按所在系的系号升序排序,同一系中的学生按年龄降序排序。
select * from Student order by Sdept asc,Sage desc;
3.8.1.8 聚合查询
实例1:查询学生总人数。
select count(*) from Student;
实例2:查询选修了课程的学生人数。
select count(distinct Sno) from SC;
实例3:计算1号课程的学生平均成绩
select avg(Grade) from SC where Cno='1';
实例4:查询选修1号课程的学生最高分数
select max(Grade) from SC where Cno='1';
实例5:查询学生201215012选修课程的总学分数。
select sum(Ccredit) from SC,Course Sno='201215012' and SC.Cno=Course.Cno;
3.8.1.9 分组查询
实例:求各个课程号及相应的选课人数
select Cno,count(Sno) from SC group by Cno;
3.8.1.10 过滤查询
实例:查询选修3门以上课程的学生号
select Sno from SC group by Sno having count(*) >3;
实例:查询平均成绩大于等于90分的学生学号和平均成绩
select Sno,avg(Grade) from SC group by Sno having avg(Grade)>=90;
3.8.2 连接查询
3.8.2.1 等值连接
实例:查询每个学生及其选修课程的情况
select Student.*,SC.* from Student,SC where Student.Sno=SC.Sno;
3.8.2.2 非等值连接
实例:查询选修2号课程且成绩在90分以上的所有学生的学号和姓名。
select Student.Sno,Student.name from Studnet,SC where SC.Grade >= 90 and SC.Cno='2' and Student.Sno=SC.Sno;
3.8.2.3 自身连接
实例:查询每一们课程的间接先选课(先休的先休课程)。
select a.Cno,b.Cpno from Course a,Course b where a.Cpno=b.Cno;
3.8.2.4 外连接
实例:查询每一个学生及其选修课程的情况
select a.*,b.Cno,b.Grade from Student a left join SC b on (Studnet.Sno=SC.Sno);
3.8.2.5 多表连接
实例:查询每一个学生的学号、姓名、选修的课程名及成绩。
select Student.Sno,Sname,Cname,Grade from Student SC,Course where Student.Sno=SC.Sno and SC.Cno=Course.Cno;
3.8.3 嵌套查询
一个select-from-where语句称为一个查询块,将一个查询块嵌套在另一个查询块的where字句或having短语的条件中的查询称为嵌套查询,上层的查询块称为外层查询或父查询,下层查询块称为内层查询或子查询,SQL语言允许多层嵌套查询,既一个子查询还可以允许嵌套其他子查询,子查询不能使用order by 字句。
- 不相关子查询:子查询的查询条件不依赖于父查询,由里向外逐层处理。既每一个子查询在上级查询处理之前求解,子查询的结果用于建立其子查询的查找条件。
- 相关子查询:子查询的查询条件依赖于父查询,首先取外层查询中的表的第一个元组,根据它与内层查询相关的属性值的属性值处理查询内层查询,若where子句返回的值为真,则取此元组放入查询结果表,然后再取外层表的下一个元组,重复这一过程,直至外层表全部检测完为止。
3.8.3.1 带有比较运算符的子查询
实例:找出每个学生超过他选修课程平均成绩的课程号(相关查询)
select Sno,Cno from SC a where Grade >= (select avg(Grade) from SC b where a.Sno=b.Sno);
3.8.3.2 带有IN谓词的子查询
实例:查询与“刘晨”在同一个系学习的学生。
select Sno,Sname,Sdept from Student where Sdept in (select Sdept from Student where Sname = '刘晨');
3.8.3.3 带有ANY或ALL谓词的子查询
使用ANY或ALL谓词时必须同时使用比较运算符,语义为:
- > any: 大于子查询结果中的某个值
- > all: 大于子查询结果中的所有值
- < any: 小于子查询结果中的某个值
- < all: 小于子查询结果中的所有值
- …
- != all: 不等于子查询结果中的任何值
特定:子查询结果一般为一个属性多个值(集合)!
实例:查询非计算机科学系中比计算机科学系任意一个学生年龄小的学生姓名和年龄。
select Sname,Sage from Student where Sage < all (select Sage from Student where Sdept = 'SC') and Sdept !='SC';
3.8.3.4 带有EXISTS谓词的子查询
EXISTS和NOT EXISTS子句的返回值是一个BOOL值。 EXISTS内部有一个子查询语句(SELECT … FROM…), 我将其称为EXIST的内查询语句。其内查询语句返回一个结果集。EXISTS子句根据其内查询语句的结果集空或者非空,返回一个布尔值。
一种通俗的可以理解为:将外查询表的每一行,代入内查询作为检验,如果内查询返回的结果取非空值,则EXISTS子句返回TRUE,这一行行可作为外查询的结果行,否则不能作为结果。
- 若内层查询结果非空,则外层的where字句返回真值。
- 若内层查询结果为空,则外层的where子句返回假值。
- not exists与exists语义相反。
- 查询的每一条记录都需要逐一验证的,实现两表条件查询
主查询中将每一个行带入由exists引出的子查询,判断真假决定输出,其目标列表达式通常都用*,因为带exists的子查询只关心返回值的真假,给出列名无实际意义。
实例1:查询所有选修了1号课程的学生姓名。
select Sname from Student where exists (select * from SC where SC.Sno=Student.Sno and SC.Cno='1');
实例2:查询没有选修1号课程的学生姓名。
select * from Student where not exists (select * from SC where SC.Sno=Student.Sno and Cno='1');
3.8.4 集合查询
3.8.4 .1并操作UNION
实例1:查询计算机科学系学生及年龄不大于19岁的学生。(与or同效果)
select * from Student where Sdept='CS'
UNION
select * from Student where Sage<=19;
union:将多个查询结果合并起来,系统自动去掉重复元组。
all union:将多个查询结果合并起来时,保留重复元组。
3.8.4.2 交集作intersect
实例:查询计算机科学系的学生并且年龄不大于19岁的学生的交集。(与and同效果)
select * from Student where Sdept='CS'
intersect
select * from Student where Sage<=19;
3.8.4.3 差操作except
实例:查询计算机科学系的学生与年龄不大于19岁的学生差集。
select * from Student where Sdept ='CS'
except
select * from Student where Sage <=19;
3.8.5 派生表查询
子查询不仅可以出现在where字句中,还可以出现在from字句中,这时子查询生成的临时派生表成为主查询的查询对象。如果子查询中没有聚集函数,派生表可以不指定属性列,子查询select字句后面的列名为其缺省属性。
实例1:查找出每个学生超过他自己选修课程平均成绩的课程号。
select Sno,Cno
from SC,(select Sno,avg(Grade) from SC group by Sno) as Avg_sc(avg_sno,avg_grade)
where SC.Sno=Avg_sc.Sno and SC.Grade>=Avg_sc.avg_grade;
实例2:查询所有选修了2号课程的学生姓名。
select Sname
from Student,(select Sno from SC where Cno='1') as SC1
where Student.Sno = SC1.Sno;
3.9 数据操纵语言(DML)
3.9.1 插入
3.9.1.1 插入数据
语法格式:
insert into <表名> [(<列名1>[,<列名2>...)]
values (<常量1>[,<常量2>...]);
实例1:将一个新学生元组(学号:20220610;姓名:成成;性别:男;所在系:IS;年龄:18岁)插入表student。(一条数据)
insert into Student (Sno,Sname,Ssex,Sdept,Sage)
values ('20220610','成成','男','IS','18');
实例2:插入多条数据
insert into Student(Sno,Sname,Ssex,Sdept,Sage)
values ('20220610','成成','男','IS','18'),('20220609','田田','女','CS','17');
3.9.1.2 带字句的插入
语法格式:
insert into <表名> [<列1> [,<列2>....)]
子查询;
实例:对每一个系,求学生的平均年龄,并把结果存入数据库。
--建表
create table Dept_age (Sdept char(15), Avg_age int);
--插入数据
insert into Dept_age(Sdept,Avg_age)
select Sdept,avg(Sage) from Student group by Sdept;
3.9.2 修改
3.9.2.1 修改一条数据
语法格式:
update <表名>
set <列名>=<表达式>[,
<列名>=<表达式>]...
where <条件> ;
--查询的条件筛选后只能有一个元组(即一条记录),一般为主键或唯一属性值并且不为空。
实例:将学生20220610的年龄修改为22岁
update Student
set Sage=22
where Sno='20220610';
3.9.2.2 修改多条数据
语法格式:
update <表名>
set <列名>=<表达式>[,
<列名>=<表达式>]...
where <条件> ;
--查询的条件筛选后为多个元组(即多条记录)
实例: 将计算机科学系的年龄都增加一岁。
update Student
set Sage=Sage+1
where Sdept='SC';
3.9.2.3 带子查询的修改
语法格式:
update 表名
set <列名>=<表达式>[,
<列名>=<表达式>]...
where <带子查询的条件>;
实例:将计算机科学系的全部学生成绩置零。
update <SC>
set Grade=0
where Sno in (select Sno from Student where Sdept='SC');
3.9.3 删除
3.9.3.1 删除一条数据
语法格式:
delete from <表名>
[where <条件>];
--where子句条件筛选后只能有一个元组(即一条记录),一般为主键或唯一属性值并且不为空。
实例:删除学号为20220610的学生记录。
delete from Student
where Sno='20220610';
3.9.3.2 删除多条数据
语法格式:
delete from <表名>
[where <条件>];
--where子句条件筛选后为多个元组(即多条记录)。
实例:删除所有计算机科学系学生的记录
delete from Student
where Sdept='SC';
3.9.3.3 带子查询的删除
语法格式:
delete from <表名>
[where <带子句查询的条件>];
实例:删除计算机科学系所有学生的选课记录。
delete from SC
where Sno in (select Sno from Student where Sdept='SC');
第四章 数据库安全性
4.1 数据库安全性概述
数据库安全:是指以保护数据库系统、数据库系统服务器和数据库中的数据、应用、存储,以及相关网络连接为目的,是防止数据库系统及其数据遭到泄露、篡改或破坏的安全技术。
4.1.1 不安全因素
- 非授权用户对数据库的恶意存取和破坏
- 数据库中重要或敏感的数据被泄露
- 安全环境的脆弱性
4.1.2 安全标准
安全级别 | 定义 |
---|---|
A1 | 验证设计 |
B3 | 安全领域 |
B2 | 结构化保护 |
B1 | 标记安全保护 |
C2 | 受控的存取保护 |
C1 | 自主安全保护 |
D | 最小保护 |
4.2 数据库安全性控制
4.2.1 用户身份鉴定
- 静态口令鉴别
- 动态口令鉴别
- 生物特征鉴别
- 智能卡鉴别
4.2.2 存取控制机制
- 自主存取控制(Disctetionary Access Control,简称DAC)
- 强制存取控制(Mandatory Access Control,简称MAC)
4.2.3 权限授权回收
- 权限授权
语法格式:
grant <权限>[,<权限>]...
on <对象类型> <对象名> [,<对象类型> <对象名>]...
to <用户1>[,<用户2>]...
[with grant option];
with grant option :所授予的权限后,该用户是否有该权限的授予权。
实例1:把查询Student表权限授予用户U1。
grant select
on table Student
to U1;
实例2:把Student表和Course表的全部权限授予U2和U3。
grant all priviliges
on table Student,Course
to U2,U3;
实例3: 把对表SC的查询权限授予所有用户。
grant select
on table SC
to public;
实例4:把查询Student表和修改学生学号的权限。
grant update(Sno),select
on table Student
to U4;
实例5:把对表SC的insert权限授予U5用户,并且允许 其将该权限授予其他用户。
grant insert
on table SC
to U5
with grant option;
- 权限回收
语法格式:
revoke <权限>[,<权限>] ...
on <对象类型> <对象名> [,<对象类型><对象名>] ...
from <用户>[,<用户>] ... [cascade|restrict];
实例1.
第五章 数据库完整性
5.1 实体完整性
关系模型的实体完整性定义:create table中用primary key 定义那些列为主码。
单属性构成的码有两种说明方法:
- 定义为列级约束条件
- 定义为表级约束条件
多属性构成的主码有一种说明方法:
- 定义为表级约束条件
实例1:将Student表中的Sno属性定义为主码。
- 在列级定义主码。
create table Student(
Sno char(9) primary key,
Sname char(20) not null,
Ssex char(2),
Sage int,
Sdept char(20)
);
- 在表级定义主码
create table Student(
Sno char(9),
Sname char(20) not null,
Ssex char(2),
Sage int,
Sdept char(20),
primary key (Sno)
);
实例2:将SC表中的Sno,Cno属性定义为主码
create table SC(
Sno char(9) not null,
Cno char(4) not null,
Grade int,
primary key(Sno,Cno)
);
5.2 参照完整性
关系模型的参照完整性定义:在create table中用foreign key定义那些列为外码。
实例1:关系CS(Sno,Cno)是主码,Sno,Cno分别参照Student表的主码和Course表的主码。
create table SC(
Sno char(9) not null,
Cno char(4) not null,
Grade int,
primary key (Sno,Cno),
foreign key (Sno) references Student(Sno),
foreign key (Cno) references Course(Cno)
);
5.3 用户定义完整性
关系模型的用户定义完整性:针对某一具体应用的数据必须满足的语义要求
关系数据库管理系统提供了定义和检验用户定义完整性的机制,不必应用程序承担。
create table 时定义属性上约束条件:
- 列值非空(not null)
- 列值唯一(unique)
- 检查列值是否满足一个条件表达式(check)
实例1: 定义SC表时,说明Sno、Cno、Grade属性不允许取空
create table SC(
Sno char(9) not null,
Cno char(4) not null,
Grade int not null,
primary key (Sno,Cno),
);
实例2:建立部门表DEPT,要求部门名称Dname列取值唯一,部门编号Dep
create table DEPT(
Deptno int,
Dname char(9) unique not null,
Location char(10),
primary key (Deptno)
);
实例3: Student 表示Ssex只允许取“男”或“女”
create table Student(
Sno char(9)primary key,
Sname char(8) not null,
Ssex char(2) check (Ssex in ('男','女')),
Sage int,
Sdept char(20)
);
在create table 时使用check 短语定义元组上的约束条件,即元组级限制。
实例4:当学生的性别是男时候,其名字不能以Ms.打头。
create table Student (
Sno char(9),
Sname char(8) not null,
Ssex char(2),
Sdept int,
Sdept char(20),
primary key (Sno),
check (Sex ='男' and Sname not like 'Ms.%')
);
5.4 触发器
触发器(trigger)是用户定义在关系表上的一类由事件驱动的特殊过程。触发器保存在数据库服务器中,任何用户对表的增、删、改操作均由
服务器自动激活响应的触发器,触发器可以实施更为复杂的检查和操作,具有更精细和更强大的数据控制能力。
触发器又叫做事件-条件-动作(event-condition-action)规则,当特定的系统事件发生时,对规则的条件进行检查,如歌条件成立,则执行规则中的动作,否则不执行该动作,规则中的动作可以很复杂,通常是一段SQL存储过程。
5.4.1 定义触发器
语法格式:
create trigger<触发器名>
{before | after}<触发事件>
on <表名>
referencing new | old row as <变量>
for each{row | statement}
[when <触发条件>] <触发动作体>;
定义触发器语法说明:
- 表的拥有者才可以在表上创建触发器
- 触发器名:触发器名可以包含模式名,也可以不包括模式名;同一模式下,触发器名必须是唯一的;触发器名和表名必须在同一模式下。
- 表名;触发器只能定义在基本表上,不能定义在视图上;当基本表的数据发送变化时,将激活定义在该表上响应触发器事件的触发器
- 触发器:触发事件可以使insert、delete或update也可以是这几个事件的组合;可以是update of <触发列,…>,即进一步指明修改哪些列时激活触发器;after/before是触发器的时机
5.触发器类型:1. 行级触发器(for each row);2. 语句级触发器(for each statement)- 触发器条件:触发器被激活时,只有但触发条件未真是触发动作体才执行;否则触发动作不执行; 如果省略when触发条件,则触发动作体在触发器激活后立即执行
- 触发动作体:1. 触发动作体可以是一个匿名PL/SQL过程块,也可以是对已经创建存储过程的调用;
2. 如果是行级触发器,用户都可以在过程体中使用new和old引用事件之后的新值和旧值;
3. 如果是语句级触发器,则不能在触发动作体中使用new和old进行引用
4. 如果触发器体执行失败,激活触发器的事件就会终止执行,触发器的目标表和触发器可能影响的其他对象不会发送任何变化。
实例: 当对表SC的Grade属性进行修改时,若分数增加了10%,则将此次操作记录到下面表中;SC_U(Sno,Cno,Oldgrade,NewGrade),其中Oldgrade是修改前的分数,Newgrade是修改后的分数
create trigger SC_T
after update of Grade
on SC
referencing old row as oldTuple, new row as NewTuple
for each row
when (NewTuple.Grade>=1.1*OldTuple.Grade)
insert into SC_C(Sno,Cno,Oldgrade,NewGrade)
values(
OldTuple.Sno,
OldTuple.Cno,
OldTuple.Grade,
NewTuple.Grade
);
5.4.2 删除触发器
语法格式:
drop trigger <触发器名> on <表名>;
实例:删除触发器SC_T
drop trigger SC_T on SC;
第六章 关系数据库理论
基础概念:
- 实体(Entity):现实世界中客观存在并可以被区分的事物。比如“一个学生“,”一门课“,”一本书“等等。需要强调的是
这里所说的事物不仅仅是看得见摸得着的东西,它也可以是虚拟的,比如老师与学生的关系等 。 - 属性(Attribute):书本中解释为“实体所具有的某一特征”,由此可见,属性一开始是个逻辑概念,比如说,“性别”是“人”的一个属性。在关系数据库中,属性又是一个物理概念,属性可以看作是“表的一列”。
- 元组(Tuple):表中的一行就是一个元组
- 分量:元组的某个属性值。在一个关系数据库中,它是一个操作原子,即关系数据库在任何操作的时候,属性是”不可分的“。否则就不是关系数据库了。
- 码:表中可以唯一确定一个元组的某个属性(或属性组),如果这样的码又不止一个,那么大家都叫做候选码,从这些候选码中选择一其中一个候选码做这个关系的主码。(备注:每个候选码是最小的可以确定一个元组的属性。** 任何候选码的真子集都不能唯一确定一个元组 ** )
- 全码:如歌一个码包含了所有的属性,这个码就是全码。
- 主属性:一个属性只要在任何一个候选码中出现过,那么这个属性就是主属性。
- 非主属性:与主属性相反,没有在任何候选码中出现过,这个属性就是非主属性。
- 外码:一个属性(或属性组),它不是主码,外码参考与其他表的主码(foreign)
6.1 依赖
6.1.1函数依赖
专业定义:设R(U)是一个属性集U上的关系模式;X与Y是U的子集。若对于R(U)的任意一个可能的关系R, R中不可能存在两个元组上的属性值相等,而在Y上的属性值不等。则称"X函数确定Y"或“Y函数依赖于X”,记作X->Y。
函数依赖:在一个表里面,属性X可以映射到属性Y,也就是说知道了X就能确定Y,称X为决定因素。
注:平凡函数依赖和非平凡函数依赖在这里不做解释(实际工作和考试中涉及都很少,几乎接触不到)
6.1.4 完全函数依赖
完全函数依赖:若属性s完全函数依赖于属性集合Y(属性集合可以是:主码、候选码等),那么s不依赖于任何属性Y的真子集(即Y集合的部分属性集合)。
6.1.5 部分函数依赖
部分函数依赖:若属性r部分函数依赖于属性集合Y(属性集合可以是:主码、候选码等),那么存在r函数依赖于Y的真子集(即Y集合的部分属性集合)。
6.1.6 传递函数依赖
传递函数依赖:若属性t函数依赖属性集合Y,属性x函数函数依赖于t,在t传递函数依赖Y。
6.2 候选码
在一个表(实体表、关系表),唯一确定表的每一个元组的最小属性集合,所有其他属性完全依赖的最小集合即可视为为候选码,可以存在多个候选码。
6.3 范式
如何判定范式(范式判断步骤):
- 识别候选码:
候选码是能够唯一标识表中每一行记录的属性或属性集。
使用各种方法(如属性闭包、超键检测等)来识别所有的候选码。- 确定主码:
从候选码中选择一个作为表的主码。选择主码时,通常会考虑唯一性、最小化(即不包含多余的属性)、以及业务规则等因素。- 分析函数依赖:
函数依赖是指一个或一组属性(决定因素)的值能够唯一决定另一个属性(依赖属性)的值。
分析表中所有可能的函数依赖关系,这有助于理解数据之间的依赖性和冗余度。- 判断范式级别:
根据候选码、主码和函数依赖关系,判断表满足的范式级别(如第一范式、第二范式、第三范式等)。
第一范式(1NF):确保表的每一列都是不可分割的基本数据项,并且表中没有重复的组。
第二范式(2NF):在1NF的基础上,确保表中的所有非主属性(可视为非主码属性)完全依赖于某个确定的候选码(可直接选用主码)(即不存在部分依赖)。
第三范式(3NF):在2NF的基础上,确保表的所有非主属性(可视为非主码属性)不传递依赖于某个确定的候选码(可直接选用主码)(即不存在传递依赖)。- 规范化:
如果表不满足所需的范式级别,可能需要进行规范化处理,通过分解表来消除数据冗余和更新异常
PS: 非主属性一般表示不属于任何候选码中的属性,选定主码后,其余属性即为非主属性。
6.3.1 1NF
定义:关系(表)的属性不可再分。
6.3.2 2NF
定义:符合1NF,并且,非主属性完全依赖于主码
PS: 非主属性一般表示不属于任何候选码中的属性,选定主码后,其余属性即为非主属性。
6.3.3 3NF
定义:符合2NF,并且,消除传递依赖。
6.3.4 BCNF
定义:符合3FN,并且,主属性不依赖于非主属性。
- 3NF要求非主属性不传递依赖于候选键,但允许主属性被非主属性决定。
- BCNF则更进一步,要求任何属性(包括非主属性和主属性)都不能被非主属性所决定,这彻底消除了属性间的传递依赖和部分依赖。
7.1 事务
7.1.1 事务的概念
所谓事务是用户定义一个数据库操作序列,这些操作要么全做要不全不做,是一个不可分割的工作单位。例如,在关系数据库中,一个事务可以使一条SQL语句
、一组SQL语句或整个程序。事务和程序是两个概念,一般一个程序中包含多个事务。
7.1.2 事务的语句
在SQL语言中,定义事务的语句有三条:
begin transaction
commit
rollback
事务通常是以begin transaction开始,以commit或rollback结束,commit表示提交,即提交事务的所有操作。
7.1.3 事务的特性
- 原子性(Atomicity):事务是数据库的逻辑单位,事务中包括的诸多操作要么都做,要么都不做。
- 一致性(Consistency):事务执行的结果必须使数据库从一个一致的状态变为另一个一致的状态。因此当数据库中包含成功事务提交的结果时,就说数据库处于一致状态。如果数据库系统运行
过程中发送故障,有一些事务尚未完成就被迫中断(典型的就是银行转账,一减一加或不减不加) - 隔离性(Isolation):一个事务的执行不能被其他事务干扰,即一个事务内部的操作及使用的数据对其他并发事务是隔离的,并发执行的各个事务之间不能箱号干扰。
- 持续性(Durability):也称为永久性(permanence),指一个事务一旦提交,它对数据库的改变是永久性的,接下来的其他操作或故障不应该对其执行结果有任何影响。
事务是恢复和并发控制的基本单位
事务ACID特性可能被破坏的因数:
- 多个事务并行执行时,不同事务对同一对象的交叉执行
- 事务在执行过程中被迫强行停止
7.2 数据库恢复
尽管数据库系统采取各种保护措施来防止数据库的安全性和完整性被破坏,保证并发事务的正确执行,但是计算机系统中硬件的故障、软件的错误、用户的失误以及恶意的破坏仍是不可避免的,这些故障轻则造成运行事务非正常中断,影响数据库中数据的正常性,重则破坏数据库,使数据库中全部或部分数据丢失,
因此数据库管理系统必须具有把数据库从错误状态恢复到某一已知的正确状态的功能,这就是数据库的恢复。
7.3 故障的种类
- 事务内部的故障:事务内部的故障有的是可能事务程序本身发现的,有的是非预期的,不能由事务程序处理,事务内部更多的故障是非预期的,是不能由应用程序处理的。如运算溢出、并发事务发生死锁而被选中中撤销该事务、违法了某些完整性限制等。以后,事务故障仅指这类非预期的故障。事务故障意味着事务没有达到预期的终点
(commit或rollback),因此数据库可能处于不正确状态,恢复程序要在不影响其他事务运行的情况下,强行回滚(rollback)该事务,即撤销该事务已经做出的任何对数据库的修改,使得该事务好像根本没有启动一样。 - 系统故障(也称软故障):系统故障是指造成系统停止运行的任何事件,使得系统要重新启动。例如,特定类型的硬件错误(CPU故障)、作系统故障、DBMS代码错误、突然停电等。这类故障影响正常的正在运行的所有事务,但不破坏数据库。此时主存内容,尤其是数据库缓冲区(在内存)中的内容都丢失,所有运行事务都被非正常终止。
- 介质故障(也称硬故障):系统故障称为软故障,介质故障称为硬故障。硬故障指外存故障,如磁盘损坏、磁头碰撞,瞬时强磁场干扰。这类故障将破坏数据库或部分数据库,并影响正在存取这部分数据的所有事务。这类故障比1、2的故障发生可能性小得多,但破坏性最大。
7.4 恢复的机制
恢复机制涉及的两个主要问题:
- 如何建立冗余数据(最常见方法是数据转储和登录日志文件)
- 如何利用这些冗余数据实施数据库恢复
7.4.1 数据转储
数据转储是数据恢复中采油的基本技术。所谓转储既DBA定期将整个数据库复制到磁带或另一个磁盘上保存起来的过程。这些备用的数据文本称为后背副本或后援副本,转储是十分消耗时间和资源的,不能频繁进行。DBA应该根据数据库使用情况确定一个适当的转储周期。转储可分为静态转储和动态转储。
- 静态转储是在系统中无运行事务时进行的转储操作。
- 动态转储课克服静态转储的缺点,不用等待正在运行的用户事务结束。也不会影响新事务的运行。但是,转储结束时后援副本上的数据并不能保证正确有效。
7.4.2 登陆日志文件
登陆日志文件的格式:
日志文件时用来记录事务对数据库库的更新操作的文件。不同数据库系统采用的日志格式并不完全一样。
概括起来日志文件主要有两种格式:
一、以记录为单位的日志文件
- 各个事务的开始(begin transaction)标记
- 各个事务结束(commit或rollback)标记
- 各个事务的所有更新操作
注意:这里每个事务开始的标记、每个事务结束的标记和每个更新操作均为日志文件中的一个日志记录(log record)
登录日志文件的内容:
- 事务标记(标明是哪个事务)
- 操作的类型(插入、删除或修改)
- 操作对象(记录内部标识)
- 更新前数据的旧值(对插入操作而言,此项为空)
- 更新后数据库的新值(对删除操作而言,此项为空值)
二、 以数控块为单位的日志
日志记录的内容包括事务标识和被更新的数据块。由于将跟新前的整个块和更新后整个块都放入日志文件中,操作的类型和操作对象等信息将不必放入日志记录中。
登录日志文件的作用:
- 事务故障恢复和系统故障恢复必须用日志文件。
- 在动态转储方式中必须建立日志文件,后援副本和日志文件综合起来才能有效地恢复数据库。
- 在静态转储方式中,也可以建立日志文件。当数据库毁坏后可重新装入后援副本把数据库恢复到转储结束时刻到正确状态,然后利用日志文件,把已经完成的事务进行重新处理,对故障发生时尚未完成的事务进行撤销处理,z这样不必重新运行那些已经完成的事务程序就可以把数据库恢复到故障前某一时刻的正确方式。
登录日志文件的原则
- 登记的次序严格按并发事务执行的时间次序
- 必须先写日志文件,后写数据库
7.5 恢复的策略
当系统运行过程中发生故障,利用数据库后备副本和日志文件将可以将数据库恢复到故障前到某个一致性状态。
不同故障其恢复策略和方法不一样。
7.5.1 事务故障的恢复
事务故障是指事务在运行至正常终点前被终止,这是恢复子系统应利用日志文件撤销(undo)此事务已对数据库进行的修改。事务故障的恢复是由系统自动完成的,对用户是透明的。系统的恢复步骤是:
- 反向扫描文件日志(即从最后向前扫描日志文件),查找该事务的更新操作。
- 对该事务的更新操作执行逆操作。即将日志记录中“更新前的值”写入数据库。这样,如果记录中是插入操作,则相当于做删除操作(因此时“更新前的值”为空);若记录中是删除操作,则做插入操作;若是修改操作,则相当于用修改前值替代修改后值。
- 继续反向扫描日志文件,查找该事务的其他更新操作,并做同样处理。
- 如此下去,直至读到此事务的开始标记,事务故障恢复将完成了。
7.5.2 系统故障的恢复
系统故障造成数据库不一致状态的原因有两个,**一是未完成事务对数据库的更新可能已写入数据库;二是已提交事务对数据库的更新可能还留在缓冲区没来得及写入数据库。**因此恢复操作就要撤销故障发生时未完成的事务。重做已经完成的事务。系统故障的恢复是由系统在重新启动时自动完成的,不需要用户干预。系统恢复步骤是:
- 正向扫描日志文件(即从头扫描日志文件),找出在故障发生前已经提交的事务(这些事务既有begin transaction记录,也有commit记录),将其事务标识记入重做(redo)队列。同时找出故障发生时尚未完成的事务(这些事务只有begin transaction记录,无相应的commit记录),将其事务标识记入撤销对了。
- 对撤销队列中的各个事务进行撤销(undo)处理。进行undo处理的方法是,方向扫描日志文件,对每个undo事务的跟新执行逆操作,即将日志记录中“更新前的值”写入数据库。
- 对重做队列中的各个事务进行(redo)处理。进行redo处理的方法是:正向扫描日志文件,对每个redo事务重新执行日志文件登记操作,即将日志文件记录中“跟新后的值”写入数据中。
7.5.3 介质故障的恢复
发生介质故障后,磁盘上的物理数据和日志文件被破坏,这是最严重的一种故障,恢复方法是重装数据库,然后重做已完成的事务,具体步骤:
- 装入最新的数据库后备副本(离故障发生时刻最近点转储副本),使数据库恢复到最近一次转储时到一致性状态。对于动态转储到数据库副本,还需要同时装入转储开始时刻到故障发生前到日志文件副本,利用恢复系统故障方法(redo和undo),才能将数据库恢复到一致性状态。
- 装入相应的日志文件副本(转储结束时刻的日志文件副本)后,重做已经完成的事务。即首先扫描日志文件,找出故障发生时已经提交的事务标识,将其记入重做队列。然后正向扫描日志文件,对重做队列中的所有事务进行重做处理。即将日志记录中“更新后的值”写入数据库。
第八章 数据库并发控制
8.1 并发控制概述
事务是并发控制的基本单位,并发控制机制的任务,对并发操作进行正确调度,保证事务的隔离性,保证数据库的一致性,并发操作带来的数据不一致会导致一下问题:
- 丢失修改(Lost Update)
- 不可重复读(Non—repeatable Read)
- 读“脏”数据(Dirty Read)
为了充分利用系统资源发挥数据库贡献资源的特点,应该允许多个事务并行地执行。
- 在单处理机系统中,事务的并发执行实际上是这些并行事务的并发操作轮流交叉运行。这种并行执行方式称为交叉并发方式(interleaved Concurency)。虽然单处理机系统中的并行事务并没有真正地并发运行,但是减少了处理机的空闲时间,提高了系统的效率。
- 在多处理机系统中,每一个处理机可以运行一个事务,多个处理机可以同时运行多个事务,实现多个事务真正的并发运行。这种并发运行的方式称为同时并发方式(Simultaneous Concurrency)。
这里主要讨论数据库系统并发控制技术是以单处理机为基础,这些理论可以推广到多处理机的情况
当多个用户并发地存取数据库时就会产生多个事务同时存取同一数据的情况。若对并发操作不加控制就可能会存取和存储不正确的数据,破坏数据库的一致性。所以数据库管理系统必须提供并发控制机制。并发控制机制是衡量一个数据库管理系统性能的重要标志之一。
8.2 封锁概论
封锁是是实现并发控制的一个非常重要的技术。所谓封锁就是事务T在对某个数据对象,例如表、记录等操作之前,先向系统发出请求,对其加锁,在事务T释放它的锁之前,其他事务不能更新此数据库对象。
确切的控制由封锁的类型决定。基本的封锁类型有两种:排它锁🔒(Exclusive Locks,简称X锁)和共享锁(Share Locks,简称S锁)。
- 排它锁又称写锁(X锁):若事务T对数据对象A加上X锁,则只允许T读取和修改A,其他任何事务都不能再对A加任何类型的锁,知道T释放A上的锁。
- 共享锁又称读锁(S锁):若事务T对数据对象A加上S锁,则事务T可以读A但不能修改A,其他事务只能再对A加S锁,而不能加X锁,知道T释放A上的S锁。这就保证了其他事务可以读A,但在T释放A上的S锁之前不能对A做任何修改。
8.3 封锁协议
在运用X锁和S锁这两种基本封锁,对数据对象加锁时,还需要约定一些规则,例如何时申请X锁和S锁、持续时间、何时释放等。这些规则称为封锁协议(Locking Protocol)
- 一级封锁协议:事务T在修改数据R之前必须先对其加X锁,直到事务结束才释放。事务结束包括正常结束(commit)和非正常结束(rollback)。一级封锁协议可防止丢失修改,并保证事务T是可恢复的。在一级封锁协议中,如果仅仅是读数据不对其修改,是不需要加锁的,所以它不能保证可重复读和不读“脏”数据。
- 二级锁协议:一级锁协议加事务T在读取数据R之前必须先对其加S锁,读完后即可释放S锁。二级锁协议除了防止丢失修改,还可进一步防止读“脏”数据。在二级封锁协议中,由于读完数据后即可释放S锁,所以它不能保证可重复读。
- 三级封锁协议:一级锁协议加上事务T在读取数据R之前必须先对其加S锁,直到事务结束才释放。三级封锁协议除了防止修改和不读“脏”数据外,还进一步防止了不可重复读。
上面三级协议的主要区别是:什么操作需要申请封锁,以及何时释放封锁。
重复读:是指在同一个事务中,反复读取一个数据,前后读取的数据相同。
8.4 活锁和死锁
和操作系统一样,封锁的方法可能会引起活锁和死锁。
- 活锁:如果事务T1封锁了数据R,事务T2又请求封锁R,于是T2等待。T3也请求封锁R,当T1释放R上的封锁之后数据库管理系统首先批准了T3的请求,T2仍然等待。然后T4又请求封锁R,当T3释放R上的封锁之后又批准了T4的请求……T2有可能永远等待,这就是活锁的情形。避免活锁的简单方法是采用队列的方式进行请求封锁。
- 四锁:如果事务T1封锁了数据R1,T2封锁了数据R2,然后T1又请求封锁R2,因T2已经封锁了R2,于是T1等待T2释放R2上的锁。接着T2又申请封锁R1,因T1已经封锁了R1,T2也只能等待T1释放R1上的锁。这样就出现了T1在等待T2,而T2又在等待T1的局面,T1和T2两个事务永远不能结束,形成死锁。
死锁的预防:
- 一次封锁法:要求每个事务必须一次将所有要使用的数据全部加锁,否则就不能继续执行,一次加锁法虽然有效防止死锁发生,但存在以下问题:
- 扩大了封锁的范围,从而降低了系统的并发度。
- 数据库中的数据是不断变化的,原来不要去封锁的数据,在执行过程中可能会变成封锁对象,所以很难事先精准地确定每个事务所要加锁的对象,为此只能扩大封锁范围将事务在执行过程中可能需要封锁的数据对象全部加锁,这就进一步降低了并发度。
- 顺序封锁法:顺序封锁法是预先对数据对象规定一个封锁顺序,所有事务都按这个顺序实行封锁。例如在B数结构的索引中,可规定封锁的顺序从根节点开始,然后是下一级的子节点,逐级封锁。顺序封锁可有效地防止死锁,但同样有以下问题:
- 数据库系统中封锁对象极其多,并且随着数据的插入、删除等操作而不断变化,要维护这样的顺序结构非常困难,成本很高。
- 事务的封锁请求可随着事务的执行而动态地决定,很难事先确定每一个事务要封锁一些对象,因此也就很难按规定的顺序去施加封锁。
死锁的诊断
- 超时法:如果一个事务的等待时间超过了规定的时限,就认为发生了死锁
- 等待图法:事务等待图是一个有向图G=(T,U),T为结点点集合,每个结点表示正在运行的事务;U为边的集合,每条边表示事务等待的情况。若T1等待T2,则T1,T2之间化一条有向边从T1指向T2,事务等待动态图反映了所有事务等待情况,并发控制子系统周期性地(比如每隔1分钟)检查事务等待图,如果事务等待图中存在回路,则表示系统中出现了死锁。
8.5 并发调度的可串行性
多个事务的并发执行是正确的,当且仅当其结果与其按某一次序执行时的结果是相同,我们称这种调度策略为可串行化的调度。可串行(Serializability)是并发事务正确性的准则。 按这个准则规定,一个给定的并发调度,当且仅当它是可串行化的,才认为是正确调度。为了保证并发操作的正确性,DBMS的并发控制机制必须提供一定的手段来确保调度是可串行化的,从理论上讲,在某一事务执行时禁止其他事务执行的调度策略一定是可串行化的调度,这也是最简单的调度策略,但这种方法是不可取的,这使用户不能充分共享数据库资源,目前DBMS普遍采用封锁方式来实现并发调度的可串行行,从而保证调度的正确性。两段锁(Two-Phase Locking 简称2PL)协议就是保证并发调度可串行性的封锁协议。除此之外还有乐观方法等来保证调度的正确性。