数据库系统
绪论
数据库系统概述
数据(Data)是描述事物的符号记录,是对客观事物的属性的度量或表达,是可以鉴别的、可以被计算机处理的符号。
数据库(Database, DB)是长期存储在计算机内、有组织的、可共享的大量数据的集合。数据库中的数据按一定的数据模型组织、描述和存储,具有较小的冗余度、较高的数据独立性和易扩展性,并可为各种用户共享。
数据库系统(Database System, DBS)是由数据库、数据库管理系统(及其应用开发工具)、应用程序和数据库管理员(DBA)组成的存储、管理、处理和维护数据的系统。
数据库管理系统(Database Management System, DBMS)位于用户与操作系统之间,是一层数据管理软件,是基础软件,也是一个大型复杂的软件系统。DBMS 的主要功能包括:
- 数据定义功能:提供数据定义语言(DDL),定义数据库中的数据对象。
- 数据操纵功能:提供数据操纵语言(DML),实现对数据库的基本操作。
- 数据控制功能:实现数据的安全性、完整性控制,以及并发控制。
- 数据组织、存储和管理:提供多种存取方法,提高存储效率和存取速度。
- 数据库的建立和维护功能:提供数据库初始数据的转入、转储、恢复、重组和性能监视等工具。
- 其他功能:如通信、网络功能等。
数据库发展阶段
数据库技术的发展大致经历了以下几个阶段:
-
人工管理阶段(20 世纪 50 年代中期以前):
- 数据不保存。
- 数据不共享。
- 数据不独立。
- 应用程序管理数据。
-
文件系统阶段(20 世纪 50 年代中期至 60 年代中期):
- 数据可长期保存。
- 文件记录的概念。
- 记录格式化和文件结构化。
- 缺点:数据冗余、不一致性、应用程序依赖于文件、数据间联系弱、安全性差。
-
数据库系统阶段(20 世纪 60 年代末至今):
- 早期数据库系统:层次模型和网状模型数据库系统(如 IMS、IDMS)。
- 关系数据库系统(20 世纪 70 年代):基于关系模型,具有坚实的数学基础和简单的用户抽象(如 System R、Oracle、DB2、SQL Server)。
- 新一代数据库系统(20 世纪 80 年代中期以后):面向对象数据库、对象关系数据库、XML 数据库、NoSQL 数据库、NewSQL 数据库等。
数据模型
数据模型是对现实世界数据特征的抽象,是数据库系统的核心和基础。一个数据模型通常由数据结构、数据操作和数据完整性约束三部分组成。
数据模型分类
-
概念模型:
- 按用户的观点对数据和信息建模,主要用于数据库设计的概念级,与具体的 DBMS 无关。
- 最常用的概念模型是实体-联系模型(E-R 模型)。
-
逻辑模型:
- 按计算机系统的观点对数据建模,主要用于数据库设计的逻辑级,与具体的 DBMS 有关。
- 主要包括:层次模型、网状模型、关系模型、面向对象模型等。
-
物理模型:
- 对数据最底层的抽象,描述数据在存储介质上的存储结构和存取方法,是面向计算机系统的。
E-R 图
**实体-联系模型(Entity-Relationship Model, E-R 模型)**是用于概念设计的工具,由美国学者 P.P.S.Chen 于 1976 年提出。它提供了一种清晰、直观地表达现实世界概念的方法。
E-R 模型的基本概念:
-
实体(Entity):
- 客观存在并可相互区别的事物称为实体。
- 实体可以是具体的人、事、物,也可以是抽象的概念或事件。
- 实体集是具有相同属性的实体的集合。
-
属性(Attribute):
- 实体所具有的某一特性称为属性。
- 一个实体可以由多个属性来描述。
- 属性的类型:简单属性、复合属性、单值属性、多值属性、派生属性。
-
码(Key):
- 能唯一标识实体的属性或属性集称为码。
-
联系(Relationship):
- 表示实体之间的关联,是现实世界中事物内部以及事物之间的联系在数据模型中的反映。
- 联系的类型:1:1(一对一)、1:n(一对多)、m:n(多对多)。
E-R 图是 E-R 模型的图形表示方法,常用符号有:
- 矩形:表示实体集。
- 椭圆:表示属性。
- 菱形:表示联系集。
- 线段:连接属性与实体集、实体集与联系集。
E-R 图示例:学生与课程的关系
- 实体集:学生、课程
- 联系:选修(多对多)
- 属性:学生(学号、姓名、年龄)、课程(课程号、课程名、学分)
常用的数据模型
层次模型
层次模型是数据库系统中最早出现的数据模型之一,由 IBM 公司于 20 世纪 60 年代提出。
特点:
- 数据结构呈树形结构,有且仅有一个结点没有父结点,称为根结点。
- 除根结点外,其他结点有且仅有一个父结点,可以有零个或多个子结点。
- 结点之间是 1:n(一对多)的联系。
优点:
- 结构简单清晰。
- 查询和更新效率高。
- 提供了良好的完整性支持。
缺点:
- 现实世界中很多联系是非层次的,难以直接表示。
- 删除父结点时,其所有子结点也会被删除。
- 增加结点类型困难。
代表系统:IBM 的 IMS(Information Management System)
网状模型
网状模型由 CODASYL(数据系统语言协商会)于 20 世纪 60 年代末提出。
特点:
- 数据结构是有向图结构,允许多个结点没有父结点。
- 一个结点可以有多个父结点和多个子结点。
- 结点之间可以是 m:n(多对多)的联系。
优点:
- 能够更自然地表示现实世界中的复杂联系。
- 具有良好的性能和存取效率。
缺点:
- 结构复杂,不直观。
- 应用程序必须对复杂的指针结构进行操作,增加了编程的复杂性。
- 数据独立性差。
代表系统:IDMS(Integrated Database Management System)
关系模型
关系模型由 IBM 公司的 E.F.Codd 博士于 1970 年提出,是目前最主要的数据库模型。
特点:
- 数据结构是一张二维表,称为关系。
- 关系是一组具有相同属性的元组(tuple)的集合。
- 关系模型建立在严格的数学基础上。
优点:
- 建立在坚实的数学基础上。
- 概念单一,易于理解。
- 数据独立性高。
- 有统一的、非过程化的语言(SQL)。
缺点:
- 查询效率相对较低(相比于层次和网状模型)。
- 难以表示复杂的语义约束。
代表系统:Oracle、MySQL、SQL Server、DB2 等
面向对象模型
面向对象模型在 20 世纪 80 年代末出现,将面向对象的概念引入到数据库中。
特点:
- 数据和操作封装为对象。
- 对象具有唯一的标识(OID)。
- 支持类与类之间的继承关系。
- 支持复杂对象的表示。
优点:
- 能够表示复杂的数据结构和语义。
- 与面向对象编程语言直接兼容。
- 支持多媒体数据。
缺点:
- 标准化程度低。
- 性能优化困难。
- 市场接受度低。
代表系统:O2、ObjectStore、GemStone 等
数据库系统的结构
数据库系统的结构主要指的是数据库管理系统的体系结构,它定义了数据库中数据的组织方式和处理方法。按照数据抽象的层次,可以分为三级模式结构。
三级模式结构
三级模式结构是 ANSI/SPARC(美国国家标准协会/系统规划与需求委员会)于 1975 年提出的,包括外模式、模式和内模式三个层次。
-
外模式(External Schema):
- 也称为子模式或用户模式。
- 描述了数据库中与特定用户组相关的局部数据视图。
- 一个数据库可以有多个外模式。
- 同一模式可以导出多个外模式。
-
模式(Schema):
- 也称为概念模式或逻辑模式。
- 描述了数据库中全局的逻辑结构和特征。
- 对数据的逻辑结构、联系、约束等进行定义。
- 一个数据库只有一个模式。
-
内模式(Internal Schema):
- 也称为存储模式。
- 描述了数据库的物理存储结构和存取方法。
- 一个数据库只有一个内模式。
数据独立性
数据独立性是指数据与程序的相互独立性,是数据库系统的重要特征,分为两类:
-
物理数据独立性:
- 指应用程序和数据库逻辑结构独立于数据的物理存储结构。
- 内模式改变,模式不变,应用程序不受影响。
- 由模式/内模式映射来实现。
-
逻辑数据独立性:
- 指用户的应用程序独立于数据库的逻辑结构。
- 模式改变,外模式不变,应用程序不受影响。
- 由外模式/模式映射来实现。
数据库系统的组成
数据库系统由以下几个主要部分组成:
-
数据库:
- 长期存储在计算机内、有组织的、可共享的数据集合。
-
数据库管理系统:
- 数据定义子系统:提供 DDL,定义数据库中的对象。
- 数据操纵子系统:提供 DML,实现对数据的基本操作。
- 数据控制子系统:提供数据安全性、完整性控制功能。
- 存储管理器:管理数据的物理存储和访问。
- 查询处理器:优化和执行用户查询。
- 事务管理器:保证事务的 ACID 属性。
- 数据字典:存储数据库的元数据。
-
应用程序:
- 使用 DBMS 提供的功能开发的应用系统。
-
数据库管理员(DBA):
- 负责数据库的规划、设计、实施和维护。
- 定义模式。
- 定义存储结构和访问方法。
- 数据库修改。
- 授权访问。
- 性能监控和调优。
-
用户:
- 应用程序员:开发基于数据库的应用程序。
- 最终用户:通过数据库应用程序或查询工具访问数据。
- 偶然用户:临时访问数据库的用户,通常使用查询语言。
关系数据库
关系数据结构及形式化定义
关系数据库是建立在关系模型基础上的数据库,是目前最主要的数据库类型。关系模型由 IBM 的 E.F.Codd 于 1970 年提出,它用二维表格结构表示实体及实体间的联系。
关系的基本概念:
- 关系:对应一张二维表,由行和列组成。
- 元组:对应表中的一行,表示一个实体或一个联系的实例。
- 属性:对应表中的一列,表示实体或联系的一个特性。
- 码:可以唯一标识一个元组的属性集称为候选码,从中选定一个作为主码。
- 域:属性的取值范围,即一组相同数据类型的值的集合。
- 分量:元组中的一个属性值。
- 关系模式:对关系的描述,一般表示为 R(A₁, A₂, …, Aₙ),其中 R 为关系名,A₁, A₂, …, Aₙ 为属性名。
关系的性质:
- 列同质性:每一列中的数据类型相同。
- 不同列可允许不同的数据类型。
- 列的顺序无关紧要:列的次序可以任意交换,不影响关系的实际含义。
- 行的顺序无关紧要:行的次序可以任意交换,不影响关系的实际含义。
- 行列交叉处的每个值都是不可分的原子值。
- 不允许表中有完全相同的元组:每个元组都是唯一的。
关系代数是一种抽象的查询语言,是一种过程化的语言,用对关系的运算来表达查询。
关系操作
关系操作是对关系进行查询和修改的操作,基本操作包括:
- 查询操作:查询关系中满足条件的元组。
- 插入操作:向关系中添加新的元组。
- 删除操作:从关系中删除元组。
- 修改操作:更新关系中的元组。
关系代数操作分为:
-
传统的集合操作:
- 并(Union):
- 差(Difference):
- 交(Intersection):
- 笛卡尔积(Cartesian Product):
-
专门的关系操作:
- 选择(Selection):
- 投影(Projection):
- 连接(Join):
- 自然连接:
- θ 连接:
- 外连接:保留不匹配的元组,分为左外连接、右外连接和全外连接。
- 除(Division): 得到的是 R 中满足条件的元组在 S 中属性上投影所构成的集合。
关系演算是一种非过程化的语言,只描述要获取什么数据,而不指明如何获取。分为:
- 元组关系演算:以元组变量作为基本对象,如 QUEL 语言。
- 域关系演算:以域变量作为基本对象,如 QBE 语言。
关系的完整性
关系的完整性是指数据库中数据应满足的约束条件,用以保证数据的正确性、有效性和一致性。
关系模型的三类完整性约束:
-
实体完整性:
- 规则:关系的主码不能取空值(NULL)。
- 原因:主码用于唯一标识一个元组,若主码取空值,则无法唯一标识元组。
-
参照完整性:
- 规则:如果关系 R 的外码 FK 是关系 S 的主码 PK,则 R 中任何元组在 FK 上的值要么取空值,要么等于 S 中某个元组在 PK 上的值。
- 原因:确保引用的实体必须存在。
-
用户定义的完整性:
- 规则:针对特定应用环境的约束条件,由用户自定义。
- 例如:学生年龄必须在 15 到 30 岁之间、职工工资不得低于最低工资标准等。
触发器和存储过程也是维护数据完整性的重要机制。
关系代数
关系代数是一种抽象的查询语言,是一种过程化的语言,用对关系的运算来表达查询。
关系数据库标准语言 SQL
SQL 概述
**SQL(Structured Query Language,结构化查询语言)**是关系数据库的标准语言,由 IBM 的 System R 项目组在 20 世纪 70 年代开发,最初称为 SEQUEL。SQL 是一种综合性的数据库语言,集数据定义语言(DDL)、数据操纵语言(DML)、数据控制语言(DCL)于一体。
SQL 的特点:
- 综合统一:集 DDL、DML、DCL 于一体。
- 高度非过程化:用户只需指明”做什么”,不必指明”怎么做”。
- 面向集合的操作方式:操作对象和结果都是元组的集合。
- 以同一种语法结构提供多种使用方式:可以交互式使用,也可以嵌入到高级语言中使用。
- 语言简洁,易学易用。
数据定义
创建表:
CREATE TABLE 表名 (
列名1 数据类型 [列级约束条件],
列名2 数据类型 [列级约束条件],
...,
[表级约束条件]
);
常用数据类型:
- 字符串:CHAR(n)、VARCHAR(n)、TEXT
- 数值:INT、FLOAT、DECIMAL(p,d)
- 日期时间:DATE、TIME、DATETIME、TIMESTAMP
- 布尔:BOOLEAN
- 二进制:BLOB、BINARY(n)
约束条件:
- PRIMARY KEY:主键约束
- FOREIGN KEY:外键约束
- UNIQUE:唯一约束
- NOT NULL:非空约束
- CHECK:检查约束
- DEFAULT:默认值约束
示例:
CREATE TABLE Student (
Sno CHAR(9) PRIMARY KEY,
Sname VARCHAR(20) NOT NULL,
Ssex CHAR(2) CHECK (Ssex IN ('男', '女')),
Sage INT CHECK (Sage BETWEEN 15 AND 30),
Sdept VARCHAR(20)
);
CREATE TABLE Course (
Cno CHAR(4) PRIMARY KEY,
Cname VARCHAR(40) NOT NULL,
Cpno CHAR(4),
Ccredit INT,
FOREIGN KEY (Cpno) REFERENCES Course(Cno)
);
CREATE TABLE SC (
Sno CHAR(9),
Cno CHAR(4),
Grade FLOAT CHECK (Grade BETWEEN 0 AND 100),
PRIMARY KEY (Sno, Cno),
FOREIGN KEY (Sno) REFERENCES Student(Sno),
FOREIGN KEY (Cno) REFERENCES Course(Cno)
);
修改表:
-- 添加列
ALTER TABLE 表名 ADD 列名 数据类型 [约束条件];
-- 修改列定义
ALTER TABLE 表名 MODIFY 列名 数据类型 [约束条件];
-- 删除列
ALTER TABLE 表名 DROP COLUMN 列名;
-- 添加约束
ALTER TABLE 表名 ADD CONSTRAINT 约束名 约束定义;
-- 删除约束
ALTER TABLE 表名 DROP CONSTRAINT 约束名;
删除表:
DROP TABLE 表名 [CASCADE | RESTRICT];
- CASCADE:级联删除,同时删除依赖于该表的所有对象。
- RESTRICT:限制删除,如果有对象依赖于该表,则不允许删除。
数据查询
SQL 查询是 SQL 语言的核心功能,基本结构为:
SELECT [DISTINCT] <目标列表达式> [别名]
FROM <表名或视图名> [别名]
[WHERE <条件表达式>]
[GROUP BY <列名> [HAVING <条件表达式>]]
[ORDER BY <列名> [ASC|DESC]];
单表查询:
- 选择特定列:
SELECT Sno, Sname, Sdept
FROM Student;
- 选择所有列:
SELECT *
FROM Student;
- 使用 WHERE 子句指定条件:
SELECT Sno, Sname, Sage
FROM Student
WHERE Sage < 20;
- 使用 ORDER BY 子句排序:
SELECT *
FROM Student
ORDER BY Sage DESC;
- 使用聚集函数:
SELECT COUNT(*) AS 学生总人数,
AVG(Sage) AS 平均年龄,
MAX(Sage) AS 最大年龄,
MIN(Sage) AS 最小年龄
FROM Student;
- 使用 GROUP BY 分组:
SELECT Sdept, COUNT(*) AS 系人数
FROM Student
GROUP BY Sdept;
- 使用 HAVING 过滤分组:
SELECT Sdept, AVG(Sage) AS 平均年龄
FROM Student
GROUP BY Sdept
HAVING AVG(Sage) > 20;
多表连接查询:
- 内连接(等值连接):
SELECT Student.Sno, Student.Sname, SC.Cno, SC.Grade
FROM Student, SC
WHERE Student.Sno = SC.Sno;
- 自然连接(使用 NATURAL JOIN):
SELECT Sno, Sname, Cno, Grade
FROM Student NATURAL JOIN SC;
-
外连接:
- 左外连接:
SELECT Student.Sno, Student.Sname, SC.Cno, SC.Grade FROM Student LEFT JOIN SC ON Student.Sno = SC.Sno;
- 右外连接:
SELECT Student.Sno, Student.Sname, SC.Cno, SC.Grade FROM Student RIGHT JOIN SC ON Student.Sno = SC.Sno;
- 全外连接:
SELECT Student.Sno, Student.Sname, SC.Cno, SC.Grade FROM Student FULL JOIN SC ON Student.Sno = SC.Sno;
-
自连接(表与自身连接):
SELECT C1.Cno, C1.Cname, C2.Cno AS 先修课号, C2.Cname AS 先修课名
FROM Course C1, Course C2
WHERE C1.Cpno = C2.Cno;
嵌套查询(子查询):
- 带 IN 谓词的子查询:
SELECT Sno, Sname
FROM Student
WHERE Sdept IN (SELECT Sdept FROM Student WHERE Sname = '张三');
- 带比较运算符的子查询:
SELECT Sno, Cno
FROM SC
WHERE Grade > (SELECT AVG(Grade) FROM SC);
- 带 EXISTS 谓词的子查询:
SELECT Sno, Sname
FROM Student
WHERE EXISTS (SELECT * FROM SC WHERE SC.Sno = Student.Sno AND Cno = '001');
- 带 ANY/ALL 谓词的子查询:
SELECT Sno, Cno, Grade
FROM SC
WHERE Grade >= ALL (SELECT Grade FROM SC WHERE Cno = '002');
集合查询:
- 并操作(UNION):
SELECT Cno FROM Course WHERE Ccredit > 3
UNION
SELECT Cno FROM SC WHERE Grade > 90;
- 交操作(INTERSECT):
SELECT Sno FROM SC WHERE Cno = '001'
INTERSECT
SELECT Sno FROM SC WHERE Cno = '002';
- 差操作(EXCEPT):
SELECT Sno FROM Student
EXCEPT
SELECT Sno FROM SC;
数据更新
插入数据:
- 插入一条元组:
INSERT INTO Student(Sno, Sname, Ssex, Sage, Sdept)
VALUES ('201215128', '张三', '男', 20, 'CS');
- 插入子查询结果:
INSERT INTO Dept_Avg(Sdept, Avg_Sage)
SELECT Sdept, AVG(Sage)
FROM Student
GROUP BY Sdept;
更新数据:
- 更新单个元组:
UPDATE Student
SET Sage = 21
WHERE Sno = '201215128';
- 更新多个元组:
UPDATE Student
SET Sage = Sage + 1
WHERE Sdept = 'CS';
- 带子查询的更新:
UPDATE SC
SET Grade = Grade * 1.1
WHERE Sno IN (SELECT Sno FROM Student WHERE Sdept = 'CS');
删除数据:
- 删除单个元组:
DELETE FROM Student
WHERE Sno = '201215128';
- 删除多个元组:
DELETE FROM SC
WHERE Cno = '001';
- 带子查询的删除:
DELETE FROM SC
WHERE Sno IN (SELECT Sno FROM Student WHERE Sdept = 'CS');
- 删除表中所有元组:
DELETE FROM SC;
-- 或使用TRUNCATE(效率更高)
TRUNCATE TABLE SC;
创建视图
视图是从一个或多个基本表(或视图)导出的虚拟表。视图不存储数据,只存储视图的定义。
创建视图的语法:
CREATE VIEW 视图名 [(列名列表)]
AS SELECT语句
[WITH CHECK OPTION];
视图的特点:
- 简化用户操作:将复杂的查询封装在视图定义中。
- 重用 SQL 语句:避免重复编写相同的查询语句。
- 提高安全性:只允许用户访问视图中的特定数据。
- 提供数据独立性:视图可以屏蔽基本表的结构变化。
- 视图的更新限制:并非所有视图都是可更新的。
视图示例:
- 创建简单视图:
CREATE VIEW CS_Student
AS SELECT Sno, Sname, Sage
FROM Student
WHERE Sdept = 'CS';
- 创建带表达式的视图:
CREATE VIEW Student_Grade(Sno, Sname, Cno, Grade, Rank)
AS SELECT Student.Sno, Sname, Cno, Grade,
RANK() OVER (PARTITION BY Cno ORDER BY Grade DESC)
FROM Student, SC
WHERE Student.Sno = SC.Sno;
- 创建带检查选项的视图:
CREATE VIEW CS_Student
AS SELECT Sno, Sname, Sage, Sdept
FROM Student
WHERE Sdept = 'CS'
WITH CHECK OPTION;
使用视图:
-- 查询视图
SELECT * FROM CS_Student WHERE Sage < 20;
-- 通过视图更新数据(如果视图允许更新)
UPDATE CS_Student SET Sage = 21 WHERE Sno = '201215128';
删除视图:
DROP VIEW 视图名 [CASCADE];
CASCADE 选项表示级联删除,会同时删除依赖于该视图的其他视图。
数据库安全性
数据库安全性概述
数据库安全性是指保护数据库免受未授权的访问、破坏或错误使用的能力。随着数据库系统的广泛应用,其中存储的数据越来越敏感和重要,因此数据库安全性已成为数据库系统的一个关键方面。
数据库安全性控制
数据库安全性控制通常包括以下几个方面:
-
用户标识和鉴别:
- 通过用户账号和密码确认用户身份。
- 使用口令、硬件标识卡、生物识别技术等进行身份验证。
- 通常是数据库管理系统的第一道防线。
-
存取控制:
- 控制用户对数据库中数据对象的访问权限。
- 主要通过授权机制实现。
- 常见的访问权限包括:读取、插入、修改、删除等。
-
视图机制:
- 创建视图,只允许用户看到特定的数据子集。
- 隐藏敏感数据,实现数据的逻辑独立性。
- 增强了数据安全性,同时简化了用户的操作。
-
审计功能:
- 跟踪并记录用户对数据库的访问和操作。
- 发现可疑活动并分析安全漏洞。
- 提供追责的法律依据。
-
数据加密:
- 对敏感数据进行加密存储和传输。
- 即使数据被窃取,没有密钥也无法理解其内容。
- 包括传输加密和存储加密两种方式。
数据库的角色
角色是权限的集合,可以简化权限管理,尤其是在有大量用户的系统中。通过将权限分配给角色,然后将角色分配给用户,可以更高效地管理权限。
角色的优点:
- 简化权限管理,减少管理开销。
- 方便权限的批量授予和收回。
- 使权限管理更加灵活和模块化。
SQL 中的角色操作:
- 创建角色:
CREATE ROLE 角色名;
- 为角色授予权限:
GRANT 权限列表 ON 对象 TO 角色名;
- 将角色授予用户:
GRANT 角色名 TO 用户列表 [WITH ADMIN OPTION];
其中 WITH ADMIN OPTION 表示被授予角色的用户可以将该角色授予其他用户。
- 收回角色:
REVOKE 角色名 FROM 用户列表;
预定义角色:许多 DBMS 提供预定义的角色,如:
- DBA (Database Administrator):拥有所有权限的数据库管理员。
- CONNECT:具有连接数据库的基本权限。
- RESOURCE:可以创建表、序列等对象的用户。
- PUBLIC:所有用户都自动拥有的角色。
数据库完整性
实体完整性
实体完整性要求关系的主码不能取空值(NULL)。原因在于主码用于唯一标识一个元组,若主码取空值,则无法唯一标识元组。
参照完整性
参照完整性要求如果关系 R 的外码 FK 是关系 S 的主码 PK,则 R 中任何元组在 FK 上的值要么取空值,要么等于 S 中某个元组在 PK 上的值。原因是确保引用的实体必须存在。
用户定义的完整性
用户定义的完整性根据特定应用环境定义约束条件。例如,学生年龄必须在 15 到 30 岁之间、教师工资不得低于最低工资标准等。
完整性约束命名子句
触发器和存储过程也是维护数据完整性的重要机制。
关系数据理论
范式
范式(Normal Form, NF) 是关系数据库理论中的一个重要概念,用于评价关系模式的质量。范式是符合某种设计要求的关系模式的集合。高一级范式的关系模式必定满足低一级范式的所有要求;低一级范式的关系模式不一定满足高一级范式的所有要求。
在关系数据库设计中,通常需要介绍以下几种主要的范式:
第一范式(1NF)
定义:如果一个关系模式的所有属性都是不可分解的基本数据项,则该关系模式属于第一范式(1NF)。
- 特点:确保表中的每一列都具有原子性,即不可再分。
- 示例:
- 不符合 1NF 的情况:
Student(Sno, Sname, Course{Cno, Grade})
,其中Course
是复合属性。 - 符合 1NF 的情况:将复合属性拆分为多行记录,例如
Student(Sno, Sname)
和SC(Sno, Cno, Grade)
。
- 不符合 1NF 的情况:
第二范式(2NF)
定义:如果关系模式 R 属于 1NF,并且每个非主属性完全函数依赖于主码,则 R 属于第二范式(2NF)。
- 特点:消除非主属性对主码的部分依赖。
- 示例:
- 不符合 2NF 的情况:
SC(Sno, Cno, Sname, Grade)
,其中主码是(Sno, Cno)
,但Sname
只依赖于Sno
,存在部分函数依赖。 - 符合 2NF 的情况:将
Student(Sno, Sname)
和SC(Sno, Cno, Grade)
分开存储。
- 不符合 2NF 的情况:
第三范式(3NF)
定义:如果关系模式 R 属于 2NF,并且每个非主属性都不传递函数依赖于主码,则 R 属于第三范式(3NF)。
- 特点:消除非主属性对主码的传递依赖。
- 示例:
- 不符合 3NF 的情况:
Student(Sno, Sdept, Dname)
,其中主码是Sno
,且存在Sdept → Dname
,导致Dname
传递依赖于Sno
。 - 符合 3NF 的情况:将
Student(Sno, Sdept)
和Department(Sdept, Dname)
分开存储。
- 不符合 3NF 的情况:
巴斯-科德范式(BCNF)
定义:如果关系模式 R 属于 1NF,并且对于 R 中每个非平凡的函数依赖 X → Y,X 都包含候选码,则 R 属于巴斯-科德范式(BCNF)。
- 特点:与 3NF 类似,但更严格,消除了主属性对主码的部分和传递依赖。
- 示例:
- 不符合 BCNF 的情况:
Teach(Sno, Cno, Tno)
,其中候选码有两个:(Sno, Cno)
和(Sno, Tno)
,且存在函数依赖Tno → Cno
。 - 符合 BCNF 的情况:将关系分解为
ST(Sno, Tno)
和CT(Cno, Tno)
。
- 不符合 BCNF 的情况:
第四范式(4NF)
定义:如果关系模式 R 属于 BCNF,并且对于 R 中每个非平凡的多值依赖 X →→ Y,X 都包含候选码,则 R 属于第四范式(4NF)。
- 特点:消除非平凡且非函数依赖的多值依赖。
- 示例:
- 不符合 4NF 的情况:
SC(Sno, Cno, Tno)
,其中Sno
是主码,且存在多值依赖Sno →→ Cno
和Sno →→ Tno
,但Cno
和Tno
相互独立。 - 符合 4NF 的情况:将关系分解为
SC1(Sno, Cno)
和SC2(Sno, Tno)
。
- 不符合 4NF 的情况:
规范化
规范化的目标是通过逐步将关系模式转化为更高范式,从而消除数据冗余、更新异常、插入异常和删除异常,提高数据的一致性和正确性。
- 数据冗余:数据冗余是指同一数据多次存储,浪费存储空间并可能导致不一致性。
- 更新异常:更新异常发生在修改数据时需要同时更新多行记录,容易造成遗漏或错误。
- 插入异常:插入异常发生在无法插入某些信息,或者必须插入额外的信息才能完成插入操作。
- 删除异常:删除异常发生在删除某些信息时会导致其他有用信息的丢失。
通过规范化可以有效解决上述问题,使数据库设计更加合理。
数据依赖的公理系统
Armstrong 公理系统 是函数依赖理论中的一个重要工具,用于推导函数依赖的完备集。它包括三条基本规则以及从这些规则推导出的其他规则。
基本规则:
- 自反律:若 Y ⊆ X,则 X → Y 恒成立。
- 增广律:若 X → Y,则 XZ → YZ(Z 为任意属性集)。
- 传递律:若 X → Y 且 Y → Z,则 X → Z。
推导规则:
- 合并规则:若 X → Y 且 X → Z,则 X → YZ。
- 伪传递规则:若 X → Y 且 WY → Z,则 WX → Z。
- 分解规则:若 X → YZ,则 X → Y 且 X → Z。
通过 Armstrong 公理系统,我们可以验证函数依赖是否成立,并进一步分析关系模式是否符合特定范式的要求。
数据库设计
数据库设计概述
数据库设计是一个复杂的过程,通常分为六个主要阶段:
- 需求分析:收集和分析用户需求,定义系统的边界。
- 概念设计:将用户需求转换为概念模型(通常是 E-R 模型)。
- 逻辑设计:将概念模型转换为特定 DBMS 支持的数据模型。
- 物理设计:根据 DBMS 特性和性能需求,确定物理存储结构和访问方法。
- 数据库实现:使用特定 DBMS 的 DDL 语句创建数据库和表。
- 数据库运行和维护:定期监控数据库性能和安全,进行调整和优化。
需求分析
需求分析是数据库设计的基础,需要明确数据需求、处理需求和性能需求。
概念结构设计
概念设计是将用户需求转换为与 DBMS 无关的概念模型。在这个阶段,需要识别实体、属性和实体间的联系,并绘制 E-R 图。
逻辑结构设计
逻辑设计阶段将概念模型(E-R 图)转换为特定 DBMS 支持的数据模型(通常是关系模型)。需要进行规范化处理,消除数据冗余和异常。
物理结构设计
物理设计阶段根据 DBMS 特性和性能需求,确定物理存储结构和访问方法。包括索引、聚簇、分区等策略的设计。
数据库的实施和维护
数据库的实施阶段包括创建数据库和设置完整性约束。维护阶段包括监控性能、备份和恢复等。
数据库编程
嵌入式 SQL
嵌入式 SQL 是将 SQL 语句嵌入到宿主语言(如 C、Java、Python)中使用的 SQL 形式。
过程化 SQL
过程化 SQL 允许用户编写包含控制结构的 SQL 代码,如循环、条件判断等。
存储过程和函数
存储过程和函数是预编译的 SQL 代码块,可以提高执行效率和代码复用性。
ODBC 编程
ODBC(Open Database Connectivity)是一种标准接口,用于访问多种数据库管理系统。
关系查询处理和查询优化
关系数据库系统的查询处理
查询处理是指如何有效地执行用户的 SQL 查询。主要包括解析、优化和执行三个阶段。
关系数据库系统的查询优化
查询优化的目标是生成高效的查询执行计划。主要包括代数优化和物理优化两个步骤。
代数优化
代数优化通过重写查询表达式来减少查询处理的代价。
物理优化
物理优化通过选择合适的存取路径和执行算法来提高查询性能。
数据库恢复技术
事务的基本概念
事务是数据库管理系统中的一个重要概念,它是一组操作的集合,这些操作要么全部执行成功,要么全部不执行。
数据库恢复概述
数据库恢复技术用于在系统发生故障后将数据库恢复到一个一致的状态。
故障的种类
数据库系统可能面临以下故障:
- 事务故障:由于逻辑错误或违反完整性约束导致事务无法继续执行。
- 系统故障:操作系统崩溃、断电等情况。
- 介质故障:磁盘损坏等导致数据丢失
恢复的实现技术
数据库恢复的核心技术是基于日志文件和检查点机制。这些技术确保即使在故障发生后,数据库也能恢复到一致性状态。
日志文件
日志文件记录了所有对数据库的更新操作,包括事务标识、操作类型、受影响的数据项、修改前后的值以及时间戳等信息。通过日志文件,数据库系统可以追踪并重建事务执行过程中发生的每一步操作。
日志记录的内容
- 事务标识:每个事务都有一个唯一的标识符。
- 操作类型:如插入、删除、更新等。
- 受影响的数据项:操作所影响的表、行或列。
- 修改前的值(UNDO 信息):用于撤销未提交事务的操作。
- 修改后的值(REDO 信息):用于重做已提交事务的操作。
- 时间戳:记录操作发生的时间。
- 操作状态:如事务开始(BEGIN)、提交(COMMIT)、中止(ABORT)等。
日志类型的分类
- 物理日志:记录数据页级别的变化,适合快速恢复但依赖于存储结构。
- 逻辑日志:记录高级操作,如 SQL 语句及其等效表示,与存储结构无关。
- 物理逻辑日志:结合两者优点,提供平衡的恢复速度和适应性。
检查点机制
检查点是一个时间点,在此时间点上所有已提交事务的修改都已经写入磁盘,系统的状态是一致的。检查点机制用于缩短恢复时间和控制日志文件大小。
检查点的作用
- 减少恢复时间:系统只需从最近的检查点开始恢复,而不必从日志文件的开头开始。
- 控制日志文件大小:检查点之前的日志记录可以归档或删除,防止日志文件无限增长。
检查点的实现
- 静态检查点:暂停所有新事务的处理,将缓冲区中的所有修改写入磁盘。
- 优点:实现简单,确保一致性。
- 缺点:暂停系统活动,影响可用性。
- 模糊检查点:允许系统继续处理事务,同时进行检查点操作。
- 优点:对系统运行影响小。
- 缺点:实现复杂,恢复逻辑更复杂。
恢复算法
恢复过程通常分为三个阶段:分析阶段、REDO 阶段和 UNDO 阶段。
分析阶段
从最近的检查点开始扫描日志,确定哪些事务需要 UNDO,哪些事务需要 REDO。构建活跃事务表和脏页表。
REDO 阶段
重新执行所有需要 REDO 的操作,确保所有已提交事务的修改都反映在数据库中。
UNDO 阶段
撤销所有未提交事务的修改,按照日志记录的相反顺序执行 UNDO 操作。
恢复策略
不同类型的故障需要不同的恢复策略:
事务故障恢复
当单个事务失败时,数据库系统需要保证其原子性(Atomicity)。
- 回滚(Rollback):利用日志中的 UNDO 信息将数据恢复到事务开始前的状态。
- 保存点(Savepoint):允许事务部分回滚,提高灵活性。
系统故障恢复
当系统崩溃时,系统会根据磁盘上的数据库和日志文件进行恢复。
- 重启恢复:系统自动启动恢复过程。
- 恢复过程:分为分析、REDO 和 UNDO 三个阶段。
介质故障恢复
当存储介质损坏导致数据丢失时,利用备份数据和归档日志进行恢复。
- 完全恢复:从最近的完整备份开始,应用所有增量备份和归档日志。
- 时间点恢复:恢复到指定的时间点状态。
- 不完全恢复:仅能恢复到可用日志的最后一点。
并发控制
并发控制是数据库管理系统的核心功能之一,用于确保多个事务并发执行时保持数据的一致性和完整性。
并发控制概述
并发控制的目标是在多个事务并发执行时,保证数据库的一致性状态。常见的问题包括丢失更新、脏读、不可重复读和幻读。
并发控制的重要性:
- 一致性:确保事务执行前后数据库的完整性约束没有被破坏。
- 隔离性:确保一个事务的中间状态对其他事务不可见。
- 性能优化:在保证一致性的前提下,尽可能提高并发度。
封锁
封锁是一种常用的并发控制机制,通过加锁来限制对数据的访问权限。
封锁的基本概念
- 共享锁(S 锁):允许多个事务同时读取数据,但不允许写入。
- 排他锁(X 锁):只允许一个事务读取和写入数据,其他事务不能访问。
封锁的粒度层次结构
封锁的粒度从大到小可分为:
- 数据库锁:锁定整个数据库。
- 表锁:锁定整个表。
- 页锁:锁定一个数据页。
- 行锁:锁定表中的一行。
- 字段锁:锁定记录中的某个字段。
锁粒度的选择:
- 粗粒度锁(如表锁):开销小,但并发度低。
- 细粒度锁(如行锁):开销大,但并发度高。
封锁协议
封锁协议规定了何时以及如何对数据对象加锁和解锁,以避免并发问题。
两段锁协议
两段锁协议要求每个事务分为两个阶段:
- 扩展阶段:事务只能获得锁,不能释放锁。
- 收缩阶段:事务只能释放锁,不能获得锁。
两段锁协议能够保证调度的冲突可串行性,从而维护事务的隔离性。
活锁和死锁
活锁
活锁是指某些事务因长期等待而无法前进的现象。解决方法包括优先级机制和超时机制。
死锁
死锁是指两个或多个事务互相等待对方释放资源的现象。解决方法包括预防和检测两种方式:
- 预防死锁:通过规定加锁顺序等方式避免死锁的发生。
- 检测死锁:定期构建等待图,检测是否存在环。若检测到死锁,则选择一个“受害者”事务进行回滚。
并发调度的可串行性
并发调度的正确性可以通过可串行性来衡量。如果一个非串行调度的执行结果与某个串行调度的结果相同,则该调度是可串行化的。
冲突可串行性
- 定义:如果一个调度 S 与某个串行调度冲突等价,则称 S 是冲突可串行化的。
- 判定方法:使用冲突图法或交换法。
视图可串行性
- 定义:如果一个调度 S 与某个串行调度视图等价,则称 S 是视图可串行化的。
- 特点:冲突可串行化的调度一定是视图可串行化的,反之则不一定成立。
封锁的粒度
封锁的粒度决定了并发控制的效率和开销。通常,封锁的粒度越小,开销越大,但并发度越高。为了解决这一矛盾,引入了多粒度封锁协议。
多粒度封锁协议
- 显式锁:直接针对数据对象的锁。
- 意向锁:指示在某个粒度级别以下存在锁的意图。例如:
- 意向共享锁(IS):表示将在更细粒度的对象上加 S 锁。
- 意向排他锁(IX):表示将在更细粒度的对象上加 X 锁。
- 共享意向排他锁(SIX):表示对整个表加了共享锁,并计划对某些行加排他锁。