数据库原理 · 期末复习全攻略

基于上课课件 + 三套期末试卷 + 上机操作文档 + PTA题库全面整理

涵盖:关系理论 / SQL / 范式 / 查询优化 / 事务并发 / JDBC / 上机实战 / PTA精选

理论详解 代码示例 真题分析

一、关系数据库基础理论

1.1 基本概念

关系(Relation)必考

关系是一个二维表,由行(元组/Tuple)列(属性/Attribute)组成。每个关系有一个关系名。

例如:Restaurant(rID, rName, rAddress, City) 表示餐厅信息关系。

基本性质(选择题考点):

  • 列是同质的,每一列中的分量来自同一域
  • 不同的列可出自同一个域,每列有唯一属性名
  • 列的顺序无所谓,行的顺序无所谓
  • 任意两个元组不能完全相同(候选码保证)
  • 分量必须取原子值(满足1NF)
属性(Attribute)与域(Domain)

属性:关系中的每一列,给每个属性起一个名称即属性名。

:属性的取值范围,如 VARCHAR(10)INTFLOAT 等。

码(Key)必考

候选码(Candidate Key):能唯一标识元组且不含多余属性的属性组。

主码(Primary Key):从候选码中选定一个作为关系的唯一标识。

外码(Foreign Key):一个关系中的属性,它在另一个关系中是主码,用于建立关系间联系。

主属性:包含在任何一个候选码中的属性。非主属性:不包含在任何候选码中的属性。

1.2 关系模式

关系模式的定义

关系模式是对关系的描述,形式化表示为:R(U, D, DOM, F),简化为 R(U, F)

其中 R 是关系名,U 是属性名集合,D 是域,DOM 是属性向域的映象,F 是属性组上的函数依赖集合。

关系模式是"型"(Schema),静态的、稳定的;关系是"值"(Instance),动态的,随数据增删改而变化。

1.3 完整性约束必考

实体完整性(Entity Integrity)

主码的各个属性都不能取空值(NULL)。主码唯一标识元组,若为空则无法标识。

SQL中通过 PRIMARY KEY 约束实现。

参照完整性(Referential Integrity)

外码的值要么全部为空,要么等于被参照关系中某个元组的主码值。

SQL中通过 FOREIGN KEY ... REFERENCES 约束实现。

用户定义完整性(User-defined Integrity)

针对具体应用的约束条件,如 CHECK 约束、NOT NULLUNIQUEDEFAULT

例如:CHECK(price >= 0.0)CHECK(budget > 0)CHECK(vip=0 or vip=1)

1.4 三级模式与数据独立性选择填空

三级模式结构
  • 外模式(用户模式):数据库用户能看见和使用的局部数据的逻辑结构和特征的描述。
  • 模式(逻辑模式):数据库中全体数据的逻辑结构和特征的描述,是所有用户的公共数据视图。
  • 内模式(存储模式):数据物理结构和存储方式的描述。
两级映象与数据独立性

外模式/模式映象:保证逻辑数据独立性(模式改变时,修改映象使外模式不变)。

模式/内模式映象:保证物理数据独立性(内模式改变时,修改映象使模式不变)。

真题考点:保证逻辑数据独立性需修改外模式与模式的映射;保证物理数据独立性需修改模式与内模式的映射

二、关系代数

2.1 运算分类

两类运算

传统集合运算(水平方向,行的运算):并、差、交、广义笛卡尔积。要求参与运算的关系具有相同的目n,相应属性取自同一域。

专门的关系运算(涉及行和列):选择、投影、连接、除。

2.2 传统集合运算

运算公式含义
并 R∪SR∪S={t|t∈R∨t∈S}属于R或属于S的元组
差 R-SR-S={t|t∈R∧t∉S}属于R不属于S的元组
交 R∩SR∩S=R-(R-S)既属于R又属于S的元组
笛卡尔积 R×SR×S={trts|tr∈R∧ts∈S}列数n+m,行数k1×k2

2.3 专门的关系运算

选择 σ(Selection)

σF(R) = {t | t∈R ∧ F(t)='真'}

从行的角度选择满足条件F的元组。F为逻辑表达式,由比较运算符和逻辑运算符组成。

例:σSdept='IS'(Student) 查询信息系学生。

投影 π(Projection)

πA(R) = {t[A] | t∈R}

从列的角度选取属性A,可能取消重复行

例:πSname,Sdept(Student) 查询学生姓名和所在系。

连接 ⋈(Join)必考

等值连接:θ为"="的连接,结果保留重复列

自然连接:特殊的等值连接,比较分量必须是相同属性组,结果去掉重复列,同时从行和列角度运算。

外连接:主体表中不满足条件的元组也输出,非主体表用空值填充。

  • 左外连接 LEFT JOIN:左边表全部显示
  • 右外连接 RIGHT JOIN:右边表全部显示

自身连接:一个表与自己连接,需给表起别名。

除 ÷(Division)必考

R÷S = {tr[X] | tr∈R ∧ πY(S) ⊆ Yx},其中 Yx 为 x 在 R 中的象集。

象集Zx = {t[Z] | t∈R, t[X]=x},即 X 值为 x 时,对应的所有 Z 值集合。

用途:查询"出现在所有X的Y"类问题。如"选修了全部课程的学生"、"订过所有船的水手"。
解题步骤:①求各X值的象集 ②求S在Y上的投影 ③找象集包含πY(S)的X值。

2.4 综合例题

真题关系代数表达式

例1(除法):查询出现在所有餐厅的菜品信息,显示菜品编号、名称、单价:

πdID,dName,dPrice(Dish) ÷ πrID(Sales)

例2(选择+投影+自然连接):查询菜品名称包含"花菜"的菜品销售信息:

πdName,dPrice,rID,QTY(σdName LIKE '%花菜%'(Dish ⋈ Sales))

例3(绿色或黄色船只的预订信息):

πsid,bid(σcolor='绿' OR color='黄'(Boats ⋈ Reserves))

三、SQL语言完全指南

3.1 SQL概述选择填空

SQL分类

DDL(数据定义):CREATE / DROP / ALTER

DQL(查询):SELECT

DML(数据操作):INSERT / UPDATE / DELETE

DCL(数据控制):GRANT / REVOKE

特点:综合统一、高度非过程化、面向集合的操作方式、语言简洁易学。

3.2 数据定义(DDL)必考

CREATE TABLE 建表
CREATE TABLE Sales (     rID  VARCHAR(18),     dID  VARCHAR(18),     QTY  INT  CHECK(QTY >= 0),     PRIMARY KEY (rID, dID),     FOREIGN KEY (rID) REFERENCES Restaurant(rID),     FOREIGN KEY (dID) REFERENCES Dish(dID) );

常用约束

  • PRIMARY KEY — 主码约束(唯一且非空)
  • UNIQUE — 唯一性约束(允许空值,一表可多个)
  • NOT NULL — 非空约束
  • FOREIGN KEY ... REFERENCES — 外码约束
  • CHECK(条件) — 检查约束,如 CHECK(price >= 0.0)
  • DEFAULT — 默认值
PRIMARY KEY 与 UNIQUE 区别:主码唯一且非空,UNIQUE允许空值;一个表只能有一个主码,但可有多个UNIQUE。
ALTER TABLE 修改表
  • ADD:增加新列或约束(新增列一律为空值)
  • DROP:删除约束或列
  • MODIFY:修改列的数据类型
索引
CREATE [UNIQUE] [CLUSTER] INDEX 索引名 ON 表名(列名 [ASC|DESC]);

UNIQUE:唯一值索引,已有重复值不能建。

CLUSTER(聚簇索引):索引项顺序与表中记录物理顺序一致;每张表只能建一个;需要120%附加空间;适用于很少增删改的表。主键约束自动创建聚集索引。

升序ASC(缺省),降序DESC。

3.3 数据查询(DQL)必考

SELECT 语句完整格式
SELECT [ALL|DISTINCT] 目标列表达式[, ...] FROM 表名或视图名[, ...] [WHERE 条件表达式] [GROUP BY 列名 [HAVING 条件表达式]] [ORDER BY 列名 [ASC|DESC]];

SELECT:指定显示列(可用表达式、函数、列别名)

WHERE:分组前筛选行;HAVING:分组后筛选组

GROUP BY:分组;使用后SELECT子句只能出现分组属性和集函数

ORDER BY:排序,ASC升序(缺省),DESC降序

DISTINCT 去重

SELECT DISTINCT barcode FROM tradeDetail

DISTINCT作用于所有目标列,不能写成 SELECT DISTINCT CName, DISTINCT barcode(错误),应为 SELECT DISTINCT CName, barcode

WHERE 查询条件
查询条件谓词
比较=, >, <, >=, <=, !=, <>
确定范围BETWEEN AND, NOT BETWEEN AND
确定集合IN, NOT IN
字符匹配LIKE, NOT LIKE(%任意长度, _单个字符)
空值IS NULL, IS NOT NULL(不能用=NULL)
多重条件AND, OR(AND优先级高于OR)

LIKE通配符%代表任意长度字符串,_代表任意单个字符。ESCAPE转义:LIKE '100\%纯棉' ESCAPE '\'

集函数(5类)
函数功能
COUNT([DISTINCT|ALL]*) / COUNT(列名)计数
SUM(列名)求和
AVG(列名)平均值
MAX(列名)最大值
MIN(列名)最小值

DISTINCT取消重复值,ALL不取消(缺省)。

GROUP BY 与 HAVING高频

GROUP BY:值相等的为一组,集函数分别作用于每组。

WHERE vs HAVING:WHERE作用于基表/视图选择元组(分组前),HAVING作用于组选择组(分组后)。
WHERE中不能用集函数,HAVING中可以。

例:查询销售数量大于100的商品:

SELECT barcode, SUM(quantity) AS total FROM tradeDetail GROUP BY barcode HAVING SUM(quantity) > 100;

3.4 连接查询

连接类型

等值连接:连接运算符为=,保留重复列。

自然连接:去掉重复属性列的等值连接。

自身连接:一个表与自己连接,需起别名。

-- 自身连接:查询每门课的先修课名称 SELECT FIRST.Cno, SECOND.Cpno FROM Course FIRST, Course SECOND WHERE FIRST.Cpno = SECOND.Cno;

外连接:主体表中不满足条件的元组也输出。

-- 左外连接 SELECT Student.Sno, Sname, Cno, Grade FROM Student LEFT JOIN SC ON Student.Sno = SC.Sno;

复合条件连接(多表):

SELECT Student.Sno, Sname, Cname, Grade FROM Student, SC, Course WHERE Student.Sno = SC.Sno AND SC.Cno = Course.Cno;

3.5 嵌套查询必考

子查询分类

不相关子查询:子查询条件不依赖于父查询,由里向外逐层处理。

相关子查询:子查询条件依赖于父查询,外层取元组→处理内层→判断。

子查询不能使用ORDER BY

IN 谓词
-- 查询与刘晨同系的学生 SELECT Sno, Sname, Sdept FROM Student WHERE Sdept IN (SELECT Sdept FROM Student WHERE Sname = '刘晨');
ANY / ALL 谓词
谓词含义集函数等价
> ANY大于子查询结果中某个值> MIN
> ALL大于子查询结果中所有值> MAX
< ANY小于某个值< MAX
< ALL小于所有值< MIN
= ANY等于某个值IN
<> ALL不等于任何值NOT IN
技巧:用集函数实现通常比ANY/ALL效率高(减少比较次数)。
EXISTS / NOT EXISTS高频难点

EXISTS代表存在量词,子查询不返回数据,只返回逻辑真/假。内层查询结果非空→真值。

双重NOT EXISTS实现全称量词(必考题型):

SQL没有全称量词∀,转换公式:(∀x)P ≡ ¬(∃x(¬P))

例:查询选修了全部课程的学生:

SELECT Sname FROM Student WHERE NOT EXISTS (     SELECT * FROM Course     WHERE NOT EXISTS (         SELECT * FROM SC         WHERE Sno = Student.Sno AND Cno = Course.Cno     ) );

逻辑蕴函:p→q ≡ ¬p∨q,进一步 (∀y)p→q ≡ ¬∃y(p∧¬q)

例:查询至少选修了95002学生选修的全部课程的学生——"不存在这样的课程y,95002选修了y而x没有选"。

3.6 集合查询

集合操作
操作说明等价改写
UNION(并)列数相同,对应类型相同;自动去重OR
INTERSECT(交)MySQL不支持,用AND/IN间接实现AND
MINUS(差)MySQL不支持,用NOT IN间接实现NOT IN

ORDER BY只能出现在最后,可用数字指定排序属性:ORDER BY 1

3.7 数据更新(DML)必考

INSERT 插入
-- 插入单个元组 INSERT INTO 表名[(列名...)] VALUES(常量...);  -- 插入子查询结果 INSERT INTO 表名[(列名...)] 子查询;

真题示例:INSERT INTO project VALUES('01', 'A');

UPDATE 修改
UPDATE 表名 SET 列名=表达式[, ...] [WHERE 条件];

真题示例:将没有销售记录的菜品单价调整为原来的30%:

UPDATE Dish SET dPrice = dPrice * 0.3 WHERE dID NOT IN (SELECT DISTINCT dID FROM Sales);

真题示例:将年龄大于40的船员级别上调一级(不超过9级):

UPDATE Sailors SET rating = rating + 1 WHERE age > 40 AND rating + 1 <= 9;

真题示例:采购数量总和大于1000的商品VIP改为1:

UPDATE Product SET Vip = 1 WHERE Pno IN (SELECT Pno FROM SPBuy GROUP BY Pno HAVING SUM(inum) > 1000);
DELETE 删除
DELETE FROM 表名 [WHERE 条件];

真题示例:删除没有被预订过的船只信息:

DELETE FROM Boats WHERE bid NOT IN (SELECT DISTINCT bid FROM Reserves);

真题示例:删除单价超过500的菜品信息:

DELETE FROM Dish WHERE dPrice > 500;

3.8 视图必考

定义视图
CREATE VIEW 视图名[(列名...)] AS 子查询 [WITH CHECK OPTION];

视图是虚表,只存放定义,不存数据。基表数据变化,视图查询结果随之改变。

WITH CHECK OPTION:通过视图增删改时不得破坏视图定义中的谓词条件。

真题示例:创建水手级别统计视图:

CREATE VIEW VWS AS SELECT rating, COUNT(*) AS sCount, AVG(age) AS avgAge FROM Sailors GROUP BY rating;

真题示例:创建销售总数量在100到500之间的餐厅数量视图:

CREATE VIEW VWS AS SELECT City, COUNT(*) AS rCount FROM Restaurant r JOIN Sales s ON r.rID = s.rID GROUP BY City, r.rID HAVING SUM(QTY) > 100 AND SUM(QTY) < 500;
视图更新限制

不可更新视图:字段来自集函数、含GROUP BY、含DISTINCT、含嵌套查询涉及基表等。

视图的作用
  1. 简化用户操作
  2. 使用户以多种角度看待同一数据
  3. 对重构数据库提供一定程度的逻辑独立性
  4. 对机密数据提供安全保护

3.9 数据控制(DCL)必考

GRANT 授权
GRANT 权限[, 权限]... [ON 对象类型 对象名] TO 用户[, 用户]... [WITH GRANT OPTION];

权限:SELECT、INSERT、UPDATE、DELETE、ALL PRIVILEGES等

WITH GRANT OPTION:允许获得权限的用户再授权给其他用户(权限传播)。

真题示例:将餐厅信息表的查询权限赋给所有用户:

GRANT SELECT ON Restaurant TO PUBLIC;

真题示例:将水手信息表的age属性修改权限赋给用户U2:

GRANT UPDATE(age) ON Sailors TO U2;
REVOKE 收回权限
REVOKE 权限[, 权限]... [ON 对象类型 对象名] FROM 用户[, 用户]...;

真题示例:将对表S操作的所有权限从用户UA中收回:

REVOKE ALL PRIVILEGES ON TABLE S FROM UA;
级联收回:收回某用户权限后,该用户传播给其他用户的权限也会被级联收回。

四、函数依赖与范式理论

4.1 函数依赖必考

函数依赖定义

设 R(U) 是属性集 U 上的关系模式,X 和 Y 是 U 的子集。若对于 R(U) 的任意关系 r,r 中不可能存在两个元组在 X 上的属性值相等而在 Y 上的属性值不等,则称 Y 函数依赖于 X,记作 X → Y

简言之:若 X 的值确定,则 Y 的值也唯一确定。

函数依赖的类型

平凡/非平凡函数依赖:Y⊆X为平凡(必然成立),Y⊈X为非平凡(通常讨论的)。

完全函数依赖 X ─F→ Y:X→Y 且 X 的任何真子集 X' 都不能决定 Y。

部分函数依赖 X ─P→ Y:X→Y 但存在 X 的真子集也能决定 Y。

传递函数依赖:X→Y,Y→Z(且Y↛X),则 Z 传递依赖于 X。若 Y→X(即 X↔Y),则 Z 直接依赖于 X。

从语义推导函数依赖

"每个工程的地址、动工日期、竣工日期唯一" → 工程号 → 工程名, 动工日期, 竣工日期

"每种材料可应用于若干工程" → 材料号 → 材料名称

"每个工程使用若干材料" → (工程号, 材料号) → 使用数量

4.2 码的求解方法必考

求候选码步骤

第一步:只在函数依赖集左部出现的属性 → 必属于候选码(L类)

第二步:只在右部出现的属性 → 必不属于任何候选码(R类)

第三步:左右都出现的(LR类)和两边都没出现的(N类)→ 可能属于候选码

第四步:从 L 类出发,逐步加入 LR 类或 N 类属性,求闭包。若闭包=U,则为候选码。

闭包(Attribute Closure)

属性集 X 的闭包 X⁺ 是通过 F 能从 X 推导出的所有属性集合。

X⁺ = U,则 X 是超码;若 X 的任何真子集的闭包都不等于 U,则 X 是候选码。

典型例题

R(A, B, C, D, E)F = {AB→C, B→D, C→E}

L类:A(只在左部);R类:E(只在右部);LR类:B, C;N类:D

(AB)⁺:AB→C→E,B→D,所以 (AB)⁺ = {A,B,C,D,E} = U

去掉A:B⁺ = {B,D} ≠ U;去掉B:A⁺ = {A} ≠ U

因此 主码 = AB

4.3 范式理论核心必考

范式层级

5NF ⊃ 4NF ⊃ BCNF ⊃ 3NF ⊃ 2NF ⊃ 1NF

第一范式(1NF)

关系中每个属性都是不可再分的原子值。所有关系模式默认满足1NF。

第二范式(2NF)

R∈1NF,且每个非主属性都完全函数依赖于码(无非主属性对码的部分函数依赖)。

判断:若存在非主属性对码的部分依赖 → 不属于2NF。

:码=AB,B→D是部分依赖(B是AB的子集),不属于2NF。

第三范式(3NF)

R∈2NF,且不存在非主属性对码的传递函数依赖

等价定义:若 X→Y(非平凡),则 X 必须是超码,或 Y 是主属性。

AB→C, C→E,E 传递依赖于 AB,不属于3NF。

BC范式(BCNF)

R∈1NF,且对于每个函数依赖 X→Y(Y⊈X),X 必含候选码(每个决定因素都包含码)。

BCNF 是 3NF 的加强版,消除了主属性对码的部分和传递依赖。

关系:BCNF → 3NF → 2NF → 1NF(反方向不成立)。若 R∈3NF 且只有一个候选码,则 R∈BCNF。

范式判断流程
  1. 确认满足 1NF(通常默认满足)
  2. 检查是否存在部分函数依赖(非主属性依赖于码的子集)→ 若有,最高 1NF
  3. 检查是否存在传递函数依赖(非主属性通过中间属性依赖于码)→ 若有,最高 2NF
  4. 若无以上问题 → 属于 3NF
  5. 检查主属性是否有部分/传递依赖 → 若无,属于 BCNF

4.4 规范化分解必考

规范化到3NF的方法

原则:找出非平凡函数依赖 X→Y(X不是超码),将 Y 及其依赖属性分离,与 X 组成新关系。

R(A,B,C,D,E)F = {AB→C, B→D, C→E},码=AB

分解结果:

  • R1(A, B, C) — 主码:AB
  • R2(B, D) — 主码:B
  • R3(C, E) — 主码:C
真题例题:工程材料关系

原模式R(工程号, 工程名, 动工日期, 竣工日期, 材料号, 材料名称, 使用数量)

函数依赖:工程号→工程名,动工日期,竣工日期;材料号→材料名称;(工程号,材料号)→使用数量

主码:(工程号, 材料号) 最高范式:1NF(存在部分函数依赖)

分解到3NF

  • R1(工程号, 工程名, 动工日期, 竣工日期) — 主码:工程号
  • R2(材料号, 材料名称) — 主码:材料号
  • R3(工程号, 材料号, 使用数量) — 主码:(工程号,材料号),外码:工程号、材料号
模式分解的性质

无损连接性:分解后自然连接结果与分解前相同(不丢信息)。

保持函数依赖:分解后函数依赖仍保持。两者可同时满足或分别满足。

4.5 不好的关系模式的问题

四大异常
  • 数据冗余:相同数据重复存储
  • 更新异常:更新时维护完整性代价大
  • 插入异常:该插的数据插不进去(如新系无学生)
  • 删除异常:不该删的数据被删(如学生毕业删除系信息)

原因:不合适的数据依赖引起。解决:分解关系模式(规范化)。

4.6 PTA易错判断与选择题精选新增

判断题易错点
  • 任何二目关系(两个属性)一定属于BCNF(也满足3NF)—— 正确
  • 范式的主要目的是提高查询效率 —— 错误,目的是消除数据冗余和异常
  • 若 R.A→R.B,R.B→R.C,则 R.A→R.C(传递律)—— 正确
  • 函数依赖集F的最小函数依赖集Fm不唯一 —— 正确
  • 若X→Y和Y→Z,且X、Y、Z为互不相同的单属性,则不存在X到Z的传递函数依赖 —— 正确
  • 规范化的主要目的:维护数据的一致性(消除插入异常、删除异常、数据冗余)
选择题高频考点
  • 包含两个属性的关系模式一定满足BCNF
  • 部门关系中"部门成员"属性可能使它不满足1NF(因部门成员可再分)
  • 平凡函数依赖:AB→A(Y是X的子集)
  • 若所有属性都是主属性,则R至少属于3NF
  • R(A,B,C,D)无函数依赖时,所有属性都是候选码(都是主属性)
  • 候选码求解:R(A,B,C,D,E,F,G),F={A→B, C→D, C→F, (A,D)→E, (E,F)→G},候选码为 (A,C)

4.7 PTA关系模式分解大题精选新增

以下9道分解题来自PTA平台,涵盖了考试中关系模式分解的所有常见类型。每题包含:函数依赖→候选码→范式判断→3NF分解。
题1:工程数据表

R(工程号, 材料, 数量, 价格, 开工日期, 完工日期)

函数依赖:(工程号,材料)→(数量,价格);工程号→(开工日期,完工日期)

候选码:(工程号,材料) 范式:1NF(部分依赖:工程号→开工日期)

3NF分解:R1(工程号,开工日期,完工日期);R2(工程号,材料,数量,价格)

题2:学生成绩登记表

R(学号,姓名,性别,专业,年级,课号,课名,学分,学时,工资号,教师,成绩)

函数依赖:学号→(姓名,性别,专业,年级);课号→(课名,学分,学时,工资号);(学号,课号)→成绩;工资号→教师

候选码:(学号,课号) 范式:1NF

3NF分解:学生(学号,姓名,性别,专业,年级);课程(课号,课名,学分,学时,工资号);教师(工资号,教师);成绩(学号,课号,成绩)

题3:职工日营业额

R(职工号,日期,日营业额,部门名,部门经理)

函数依赖:(职工号,日期)→日营业额;职工号→部门名;部门名→部门经理

候选码:(职工号,日期) 范式:1NF(传递依赖:职工号→部门名→部门经理)

3NF分解:R1(职工号,部门名);R2(部门名,部门经理);R3(职工号,日期,日营业额)

题4:图书馆借阅

R(读者号,姓名,性别,住址,年龄,图书号,书名,作者,出版社,借出日期,归还日期)

函数依赖:读者号→(姓名,性别,住址,年龄);图书号→(书名,作者,出版社);(读者号,图书号)→(借出日期,归还日期)

候选码:(读者号,图书号) 范式:1NF

3NF分解:读者(读者号,姓名,性别,住址,年龄);图书(图书号,书名,作者,出版社);借阅(读者号,图书号,借出日期,归还日期)

题5:竞赛信息

R(竞赛编号,竞赛名称,竞赛组织者,竞赛开始日期,学号,学生姓名,获奖等级)

函数依赖:竞赛编号→(竞赛名称,竞赛组织者,竞赛开始日期);学号→学生姓名;(竞赛编号,学号)→获奖等级

候选码:(竞赛编号,学号) 范式:1NF

3NF分解:竞赛(竞赛编号,竞赛名称,竞赛组织者,竞赛开始日期);学生(学号,学生姓名);参赛信息(竞赛编号,学号,获奖等级)

题6:教师科研项目

R(教师号,姓名,部门号,部门名称,科研项目编号,项目名称,项目经费,担任工作,完成时间)

函数依赖:教师号→(姓名,部门号);部门号→部门名称;科研项目编号→(项目名称,项目经费);(教师号,科研项目编号)→(担任工作,完成时间)

候选码:(教师号,科研项目编号) 范式:1NF

3NF分解:教师(教师号,姓名,部门号);部门(部门号,部门名称);科研项目(科研项目编号,项目名称,项目经费);教师科研情况(教师号,科研项目编号,担任工作,完成时间)

题7:商店销售(2NF→3NF类型)

R(商店编号,商品编号,数量,部门编号,负责人)

函数依赖:(商店编号,商品编号)→部门编号;(商店编号,部门编号)→负责人;(商店编号,商品编号)→数量

候选码:(商店编号,商品编号) 范式:2NF(无部分依赖,有传递依赖)

3NF分解:R1(商店编号,商品编号,数量,部门编号);R2(商店编号,部门编号,负责人)

注意:此题属于2NF而非1NF,因为候选码(商店编号,商品编号)的任何真子集都不能决定数量或部门编号,无部分函数依赖。但存在传递依赖。
题8:学生选课教师

R(SNO, CNO, GRADE, TeaNO, TAddress)

函数依赖:(SNO,CNO)→GRADE;CNO→TeaNO;TeaNO→TAddress

候选码:(SNO,CNO) 范式:1NF(部分依赖+传递依赖)

3NF分解:R1(TeaNO,TAddress);R2(CNO,TeaNO);R3(SNO,CNO,GRADE)

题9:司机运输

R(司机编号,汽车牌照,行驶公里,车队编号,车队主管)

函数依赖:司机编号→车队编号;车队编号→车队主管;(司机编号,汽车牌照)→行驶公里

候选码:(司机编号,汽车牌照) 范式:1NF

3NF分解:R1(司机编号,车队编号);R2(车队编号,车队主管);R3(司机编号,汽车牌照,行驶公里)

3NF分解方法论总结必看
  1. 求函数依赖集F的最小覆盖
  2. 求候选码(属性分类法:L类只在左部、R类只在右部、N类两边都没出现)
  3. 判断范式等级:检查部分依赖和传递依赖
  4. 3NF分解:将F中每个函数依赖 X→A 组成一个关系模式 (X,A),合并左部相同的关系

五、数据库设计(E-R模型)

5.1 E-R模型基本要素必考

三大要素

实体(Entity):客观存在并可相互区别的事物。用矩形表示。

属性(Attribute):实体所具有的特性。用椭圆表示。

联系(Relationship):实体之间的关联。用菱形表示。

联系的类型
类型含义转换规则
1:1一对一任一方加入对方主码为外码
1:N一对多N端加入1端主码为外码
M:N多对多新建关系,主码为两端主码组合

5.2 E-R图转关系模式必考

转换规则
  1. 实体 → 一个关系模式,实体的属性即为关系属性,实体的码即为关系码
  2. 1:1联系 → 任一方加入对方主码为外码,并加入联系属性
  3. 1:N联系 → N端加入1端主码为外码,并加入联系属性
  4. M:N联系 → 新建关系,主码为两端实体主码的组合,并加入联系属性
真题示例:运动队-运动员-项目

运动队(队名, 主教练) — 运动员(编号, 姓名, 性别, 年龄) — 项目(编号, 项目名, 类别)

联系:运动队1:N运动员;运动员M:N项目(记录名次、成绩、日期)

转换结果

  • 运动队(队名, 主教练) — 主码:队名
  • 运动员(编号, 姓名, 性别, 年龄, 队名) — 主码:编号,外码:队名
  • 项目(编号, 项目名, 类别) — 主码:编号
  • 参赛(编号, 项目编号, 名次, 成绩, 日期) — 主码:(编号,项目编号),外码:编号、项目编号

5.3 PTA选择题高频考点新增

E-R图与设计阶段考点
  • E-R图图形含义:实体=矩形,属性=椭圆形,联系=菱形
  • E-R图用于建立概念模型,不依赖于计算机硬件和DBMS
  • 概念结构设计最常采用的策略是自底向上的方法(非自顶向下)
  • 描述概念模型的有力工具是E-R图(不是数据字典)
  • 合并E-R图属于概念结构设计阶段
  • 合并局部E-R图的冲突:属性冲突、命名冲突、结构冲突(无"语法冲突")
  • 物理设计阶段形成的是内模式(不是外模式)
  • 建立索引属于物理设计阶段
  • 逻辑结构设计判断是否合理的依据是规范化理论
联系类型与转换规则考点
  • 职员到部门是多对一联系
  • 机票与座位号是一对一联系
  • 学生选课是多对多联系
  • M:N联系转换时,码是M端与N端实体码的组合
  • 1:N联系转换为关系模式时,码是N端实体的码
  • 两个不同实体集+多对多联系→最少3个关系模式
  • 3个实体型+3个M:N联系→转换为6个关系(3实体+3联系)
PTA E-R图设计大题类型汇总新增

PTA平台包含以下E-R图设计大题(每题5-18分),需要掌握画图方法:

系统名称核心实体关键联系
车辆管理系统部门、车队、汽车、司机多对多+一对多混合
人事管理系统部门、岗位、职工培训、考核(M:N)
医院病房管理系统科室、病房、医生、病人1科室对多病房/多医生
旅行社管理系统景点、线路、导游、团队多对多+一对多
产品-零件-材料系统产品、零件、材料产品与零件M:N,零件与材料N:1
商业集团销售系统商店、商品、职工销售为M:N,聘用为1:N
企业集团生产系统工厂、产品、职工生产为M:N,聘用为1:N
图书借阅系统图书、出版社、读者出版社1:N图书,读者M:N图书
班级-运动员-比赛项目班级、运动员、项目班级1:N运动员,运动员M:N项目
解题要点:实体用矩形,属性用椭圆,联系用菱形。1:N联系外码放N端;M:N联系需单独建表,码为两端组合。

5.4 数据库设计步骤

六个阶段
  1. 需求分析:调查用户需求,产出数据字典、数据流图
  2. 概念结构设计:设计E-R模型(独立于DBMS)
  3. 逻辑结构设计:E-R图转关系模式,规范化
  4. 物理结构设计:选择存储结构和存取方法
  5. 数据库实施:建库、建表、录入数据
  6. 数据库运行和维护

六、查询优化

6.1 查询优化必要性选择/简答

为什么需要优化

不同的查询执行策略效率差异巨大。例如查询销售单1的商品名称和数量:

  • 策略1(先笛卡尔积):1000×10000=10⁷中间结果 → 选择 → 投影
  • 策略2(先选择):先选择orderId=1(10条)→ 自然连接 → 投影

策略2快得多。核心思想:减少中间结果。

6.2 查询优化准则必考

四条准则
  1. 选择运算尽可能先做(最重要,减小中间关系)
  2. 投影运算和选择运算同时做(避免重复扫描)
  3. 将投影运算与前面或后面的双目运算结合(减少扫描遍数)
  4. 执行连接操作前对关系适当预处理(按连接属性排序/建索引)

6.3 语法树优化必考

优化步骤
  1. 把查询转换成内部表示(语法树)
  2. 代数优化:把语法树转换成标准(优化)形式
  3. 物理优化:选择低层存取路径
  4. 生成查询计划,选择代价最小的
语法树优化关键操作:将选择条件下推到叶子节点附近(先做选择再做连接),投影运算提前。
口诀:选择下推、投影提前、连接最后。
真题示例

关系代数表达式:π水手编号,船只编号(σcolor='绿' OR color='黄'(Boats ⋈ Reserves))

优化前语法树:投影在顶部 → 选择 → 连接(Boats × Reserves)

优化后:将选择条件下推到Boats表上 → 先选择再连接 → 最后投影

优化后:πsid,bid( (σcolor='绿' OR color='黄'(Boats)) ⋈ Reserves )

6.4 关系系统分类选择

分类
  • 表式系统:仅支持表结构
  • (最小)关系系统:表 + 选择、投影、连接
  • 关系完备系统:表 + 所有关系代数操作
  • 全关系系统:支持关系模型所有特征

6.5 PTA索引与查询优化考点新增

索引判断题易错点
  • 建立索引是为了提高检索速度 —— 正确
  • 连接运算尽可能先做是查询优化最重要最基本的策略 —— 正确
  • 查询优化策略由DBMS自动选择,不是由用户确定 —— 错误,用户也可以指定
  • 索引不是越多越好 —— 索引过多会影响增删改效率
  • 每行索引记录包含指向表中数据页的逻辑指针 —— 正确
索引选择题考点
  • 索引属于内模式
  • 一个表最多1个聚集索引,可有多个非聚集索引
  • 建立唯一性索引CREATE UNIQUE INDEX 索引名 ON 表名(属性名)
  • CREATE UNIQUE INDEX IDX1 ON T(C1,C2):在C1和C2列的组合上建立唯一非聚集索引
  • 创建非聚集索引CREATE NONCLUSTERED INDEX IDX1 ON employees(phone)
  • 主码查询一般使用索引扫描
PTA SQL查询题精选

题1:查询每个学生及其选修的课程名和成绩(多表连接):

-- 写法1:传统WHERE连接 SELECT student.Sno, Sname, Cname, Grade FROM student, sc, course WHERE student.Sno = sc.Sno AND sc.Cno = course.Cno;  -- 写法2:JOIN语法 SELECT student.Sno, Sname, Cname, Grade FROM student JOIN sc ON student.Sno = sc.Sno JOIN course ON sc.Cno = course.Cno;

题2:查询选修"58130540"课程且成绩在90分以上的所有学生:

SELECT student.Sno, Sname, Cno, Grade FROM student, sc WHERE student.Sno = sc.Sno AND sc.Cno = '58130540' AND sc.Grade > 90;

填空题:R有5个属性10个元组,S有3个属性100个元组,R×S有 8 个属性,1000 条元组。

填空题(象集):关系study,cno=1时grade的象集是 {88, 90}。

七、事务管理与并发控制

7.1 事务基本概念必考

事务定义

事务:用户定义的数据库操作序列,要么全做要么全不做,不可分割的工作单位。事务是恢复和并发控制的基本单位

显式定义BEGIN TRANSACTION ... COMMIT / ROLLBACK

COMMIT:正常结束,所有更新永久生效。ROLLBACK:异常终止,回滚所有更新。

ACID特性必背
特性英文含义
原子性Atomicity事务中操作要么全做要么全不做
一致性Consistency从一个一致性状态变到另一个一致性状态
隔离性Isolation一个事务的执行不能被其他事务干扰
持续性Durability事务提交后对数据的改变是永久性的

7.2 并发操作的问题必考

三种数据不一致性
问题描述
丢失修改T1与T2读同一数据并修改,T2提交结果破坏T1结果
不可重复读T1读取后T2更新,T1无法再现前次结果(含幻影现象)
读"脏"数据T1修改后T2读取,T1被撤销恢复原值,T2读到不正确数据

7.3 封锁必考

锁的类型

排它锁(X锁/写锁):与其他锁不兼容。

共享锁(S锁/读锁):与其他S锁兼容,与X锁不兼容。

三级封锁协议必考对比
协议X锁S锁防止问题
1级修改前加X锁,事务结束释放读不加锁防丢失修改
2级同1级读前加S锁,读完即释放防丢失修改 + 读脏数据
3级同1级读前加S锁,事务结束释放防丢失修改 + 读脏数据 + 不可重复读

7.4 活锁与死锁选择填空

活锁

事务永远等待。解决:先来先服务策略。

死锁

两事务互相等待对方释放锁。

预防:一次封锁法、顺序封锁法。

诊断:超时法(可能误判)、等待图法(有向图存在回路=死锁)。

解除:选择代价最小的事务撤消,释放其所有锁。

7.5 并发调度的可串行性

可串行化

并行执行结果与某次序串行执行结果相同 → 正确调度。可串行性是并行事务正确性的唯一准则

两段锁协议(2PL)必考

内容:①读写前先获得封锁 ②释放一个封锁后不再获得任何其他封锁。

两个阶段:第一阶段扩展阶段(获得封锁),第二阶段收缩阶段(释放封锁)。

关系:两段锁协议是可串行化的充分条件(遵循2PL→可串行化;可串行化不一定遵循2PL)。

7.6 PTA事务与并发控制选择题精选新增

判断题易错点
  • MySQL中COMMIT和ROLLBACK都是事务控制语句 —— 正确
  • COMMIT后不能再ROLLBACK —— 正确
  • 事务提交后对数据库的修改是永久的 —— 正确
  • 一级封锁协议可防止丢失修改 —— 正确
  • 三级封锁协议可防止丢失修改、不可重复读、读"脏"数据 —— 正确
  • 两段锁协议可保证可串行化 —— 正确
  • 两段锁协议可能发生死锁 —— 正确
  • 死锁可以通过预防和检测来解决 —— 正确
  • 活锁可以通过先来先服务策略避免 —— 正确
选择题高频考点
  • 事务开始语句BEGIN TRANSACTION
  • 事务回滚语句ROLLBACK TRANSACTION
  • 事务的持久性由DBMS的恢复机制实现
  • 事务的隔离性由并发控制机制实现
  • 事务的原子性由UNDO操作实现
  • T1持有R的X锁,T2请求R的S锁→T2等待
  • T1持有R的S锁,T2请求R的X锁→T2等待
  • 死锁产生的条件:循环等待资源
  • 死锁检测方法:等待图(有向图存在回路=死锁)
  • 两段锁协议:事务分扩展阶段(只加锁)和收缩阶段(只解锁)

八、数据库恢复技术

8.1 故障类型选择填空

三类故障
类型原因特点
事务故障输入数据有误、运算溢出、违反完整性限制、死锁单个事务夭折
系统故障OS/DBMS错误、操作员失误、CPU故障、停电内存数据丢失,外存未受影响
介质故障磁盘损坏、磁头碰撞、强磁场可能性小但破坏性最大

8.2 恢复原理与日志必考

基本原理

冗余:利用存储在系统其它地方的冗余数据重建数据库。

实现技术:数据转储(backup)+ 登录日志文件(logging)。

日志文件登记原则必考
  1. 登记次序严格按并行事务执行的时间次序
  2. 必须先写日志文件,后写数据库(Write-Ahead Logging, WAL)
原因:若先写数据库后写日志,中间故障则无法恢复;若先写日志未写数据库,恢复时多做一次UNDO不影响正确性。
填空题:当数据库被破坏后,如果事先保存了数据库副本和日志文件,就有可能恢复数据库。

8.3 恢复策略必考

不同故障的恢复方法
故障类型恢复方法
事务故障反向扫描日志,对该事务执行逆操作(UNDO),用前像(BI)替换后像(AI)
系统故障正向扫描日志,分Redo队列(已提交)和Undo队列(未完成);先UNDO再REDO
介质故障装入最新后备副本+日志文件,重做已提交事务(REDO);需要DBA介入

8.4 PTA恢复、安全性与完整性约束考点新增

恢复判断题易错点
  • 事务故障恢复用UNDO —— 正确
  • 系统故障恢复需要UNDO和REDO —— 正确
  • 介质故障恢复用后备副本+日志文件 —— 正确
  • 静态转储不允许事务运行 —— 正确
  • 动态转储允许并发运行事务 —— 正确
  • 事务故障系统自动恢复,不必用户干预 —— 正确
安全性控制考点
  • 撤销权限用REVOKE(不是DROP/DELETE/ALTER)
  • REVOKE的CASCADE选项:级联撤销依赖该对象的权限
  • GRANT授予权限允许转授用 WITH GRANT OPTION
  • 创建角色CREATE ROLE 角色名
  • 强制存取控制安全级别高于自主存取控制
  • 数据库角色是被命名的一组权限集合
  • 所有授予的权力都可用REVOKE收回
  • 数据库加密提高安全性但降低效率
完整性约束考点
  • 完整性约束分类:实体完整性(主码)、参照完整性(外码)、用户定义完整性(CHECK等)
  • 实体完整性:主码唯一且非空
  • 参照完整性:外码要么为空,要么引用被参照表的主码
  • 外码约束作用:实现参照完整性
  • DEFAULT约束:设置默认值
  • CHECK约束:限制列值范围
  • 添加约束语法ALTER TABLE 表名 ADD CONSTRAINT 约束名 ...

九、JDBC基础

9.1 JDBC概述选择填空

JDBC的概念与由来

JDBC(Java Database Connectivity):Java语言版的ODBC,让Java程序透明地访问MySQL、Oracle、SQL Server等数据库,只需更换驱动jar包,业务代码基本不用改

本质特征:与特定数据库无关的API,隐藏不同数据库特性,提供数据库存取的平台独立性。

JDBC驱动四种类型必考
类型名称特点
Type 1JDBC-ODBC桥驱动通过ODBC访问;需客户端安装ODBC;牺牲平台独立性
Type 2本地驱动将JDBC调用转为本地调用;需安装本地代码;牺牲平台独立性
Type 3网络驱动使用网络中间服务器;支持负载均衡、连接池;有平台独立性
Type 4纯Java驱动主流方式;直接把JDBC调用转化为DBMS网络协议
两个程序包

java.sql(核心API,J2SE):使用 DriverManager、Connection 等。

javax.sql(可选扩展API,J2EE):包含JNDI资源、连接池、分布式事务,使用 DataSource 接口。

9.2 JDBC访问数据库流程必考

标准流程(必记)
// 1. 加载数据库驱动 Class.forName("com.mysql.jdbc.Driver");  // 2. 建立数据库连接 Connection conn = DriverManager.getConnection(     "jdbc:mysql://127.0.0.1:3306/db_room", "root", "123456");  // 3. 创建Statement对象 Statement stmt = conn.createStatement(); // 或 PreparedStatement pstmt = conn.prepareStatement(sql);  // 4. 执行查询返回ResultSet ResultSet rs = stmt.executeQuery("SELECT * FROM tbl_person");  // 5. 处理结果 while(rs.next()) {     String name = rs.getString("person_name"); }  // 6. 关闭资源(顺序:rs → stmt → conn) rs.close(); stmt.close(); conn.close();

核心类关系:DriverManager → Driver → Connection → Statement/PreparedStatement → ResultSet

JDBC URL语法
jdbc:<drivertype>://<host>:<port>/<dbname>

MySQL:jdbc:mysql://127.0.0.1:3306/db_room

SQLServer:jdbc:jtds:sqlserver://127.0.0.1:1433/dbname

Oracle:jdbc:oracle:thin:@192.168.118.101:1521:nbtv

9.3 Statement与查询

Statement查询模式
Statement stmt = con.createStatement(); ResultSet rs = stmt.executeQuery(sql); while(rs.next()) {     // 读取数据 } rs.close(); stmt.close();

SQL字符串构建:SQL中字符串常量用单引号,Java中用双引号

动态内容通过拼接:sql = "select * from t where a='" + a + "'"

ResultSet 读取数据

游标最初在第一行前面next() 返回boolean,移动到最后一行之后返回false。

if(rs.next()) 判断是否存在数据;while(rs.next()) 循环遍历。

读取字段:getString(1)(列序号)、getString("userid")(列名)、getInt(...)

可滚动结果集选择
Statement stmt = con.createStatement(int type, int concurrency);
type取值说明
TYPE_FORWARD_ONLY游标只能向后滚动
TYPE_SCROLL_INSENSITIVE可前后滚动,数据库变化时结果集不变
TYPE_SCROLL_SENSITIVE可滚动,数据库变化时结果集同步改变

9.4 PreparedStatement重点

原理与优势

SQL语句预编译为数据库底层内部命令,封装在PreparedStatement对象中,减轻负担、提高速度。

优势

  • 性能更好:相同SQL多次调用时只需编译一次
  • 防止SQL注入:用 ? 占位符,不需要字符串拼接
  • 支持带参数查询
String sql = "SELECT * FROM tbl_person WHERE person_no = ?"; PreparedStatement pstmt = conn.prepareStatement(sql); pstmt.setString(1, person_no);  // 给第1个 ? 赋值 ResultSet rs = pstmt.executeQuery();

9.5 增删改操作

executeUpdate vs executeQuery
方法用途返回值
executeQuery()SELECT查询ResultSet
executeUpdate()INSERT/DELETE/UPDATEint(影响行数)

插入示例

String sql = "INSERT INTO tbl_contract(person_no, room_no, from_date, to_date, contract_amount) VALUES(?,?,?,?,?)"; PreparedStatement pstmt = conn.prepareStatement(sql); pstmt.setString(1, person.getPersonNo()); pstmt.setString(2, room.getRoomNo()); pstmt.setTimestamp(3, new Timestamp(from.getTime())); pstmt.setTimestamp(4, new Timestamp(to.getTime())); pstmt.setDouble(5, amount); pstmt.executeUpdate();
数据删除的四种方式
  1. 通过ResultSet删除rs.deleteRow()
  2. 通过SQL语句DELETE FROM 表 WHERE 条件
  3. 软删除:通过字段标识删除(如设置 removeDate),不真正删除
  4. 删除控制:通过外码违约控制或代码删除前判断

9.6 事务处理必考

JDBC事务四步
// 1. 关闭自动提交,开启事务 conn.setAutoCommit(false);  // 2. 执行多条SQL pstmt1.executeUpdate(); pstmt2.executeUpdate();  // 3. 全部成功 → 提交 conn.commit();  // 4. 中途出错 → 回滚 conn.rollback();
典型场景:图书借阅涉及多表操作(增加借阅记录 + 修改图书状态),必须用事务保证一致性。
Connection对象默认为auto-commit,每条SQL语句自动提交。

9.7 时间类型处理选择

JDBC三种时间类型
类型说明精度
java.sql.Date屏蔽了时间(hh:mm:ss)到天
java.sql.Time屏蔽了日期(yyyy-MM-dd)到时分秒
java.sql.Timestamp扩充了Date,增加毫秒到毫秒

读取:rs.getDate()rs.getTime()rs.getTimestamp()

写入:pstmt.setTimestamp(3, new java.sql.Timestamp(System.currentTimeMillis()))

9.8 元数据

两种元数据

数据库元数据

DatabaseMetaData dmd = conn.getMetaData(); String name = dmd.getDatabaseProductName(); String ver = dmd.getDatabaseProductVersion();

结果集元数据

ResultSetMetaData rsmd = rs.getMetaData(); int count = rsmd.getColumnCount();     // 字段数量 String label = rsmd.getColumnLabel(1); // 字段名称

十、JDBC进阶

10.1 数据封装与OR映射简答

三种数据表现形式
  • 持久数据:存储在数据库、文件等存储介质中
  • 感官数据:用户可直接看到、听到的数据(界面显示)
  • 内存数据:程序中的变量,用JavaBean表达

应用系统核心功能 = 完成持久数据和感官数据之间的转换(通过内存数据中间状态)。

OR映射(对象关系映射)

关系数据库中的表、行、列映射到面向对象语言中的类、对象、属性:

  • 表 SystemUser → 类 BeanSystemUser
  • 表中一行 → 一个对象
  • 表中一列 → 对象一个属性

手写JDBC转换是最原始的OR映射;Hibernate、MyBatis等框架可自动完成。

JavaBean设计规范

三部分:属性、方法、事件(本课程只用属性封装数据)。

  • 可读属性:必须有 getProperty() 方法
  • 可写属性:必须有 setProperty(PropertyClass pc) 方法
  • 必须有无参构造函数

10.2 主从关系与级联

主从关系处理

提取:先查询主表得到对象,再根据外码查询从表,将结果List set到主对象属性中。

删除:要么先删从表再删主表;要么数据库设置级联删除。否则违反外键约束。

10.3 分页查询选择

分页原理

将查询结果按页大小分成多页,每次返回一页数据。

MySQL分页语法LIMIT 偏移量, 数量

-- 第21页,每页10条(偏移量 = (页码-1) × 页大小) SELECT * FROM foo WHERE b=1 LIMIT 200, 10;

SQL ServerSELECT TOP 10 * FROM foo

PageData对象
  • totalRecordCount:总记录数
  • pageCount:总页数
  • pagesize:页大小
  • pageIndex:当前页
  • data:当前页数据列表

提取步骤:①查总记录数 ②计算总页数 ③构造分页SQL,封装结果

10.4 连接池简答

连接池原理

传统方式每次访问都建立/关闭连接,开销大。连接池:

  1. 预先建立一些数据库连接
  2. 需要使用时,从池中获取一个空闲连接
  3. 使用完成后,不关闭连接,仅标识为空闲

数据源接口javax.sql.DataSource(属于JavaEE)

典型实现:c3p0(开源JDBC连接池),配置 ComboPooledDataSource 对象。

10.5 视图与索引(数据库层面)

视图

虚表,从一个或几个基本表导出。只存放定义,不存数据,不会数据冗余。

CREATE VIEW 视图名 AS 子查询 [WITH CHECK OPTION];
索引分类

按列数量:单列索引(一个索引含单列)、组合索引(含多列)。

按特性:

  • 普通索引:最基本的索引
  • 唯一索引:索引列值必须唯一,允许空值
  • 聚集索引:数据行物理存储顺序与索引顺序一致,每表只能一个,主键自动创建

索引选择原则:在WHERE、JOIN、GROUP BY、ORDER BY中出现的列;只有 =, <, >, BETWEEN, IN 及不以通配符开头的LIKE才使用索引。

10.6 DAO设计模式重点

DAO概念

DAO = Data Access Object(数据访问对象)。将与数据库相关的所有操作(增删改查)封装在独立类中,业务逻辑通过DAO访问数据库。

核心价值:隔离业务逻辑和数据访问代码,降低耦合度,提高可重用性。换数据库或改表结构只需改DAO层。

为什么DAO方法要传入Connection?考点

因为事务需要跨多个DAO方法

例如借书操作需调用两个DAO方法(插入借阅记录 + 修改图书状态),必须在同一事务中。如果DAO方法自己创建和关闭Connection,无法保证同一个连接。

事务边界应由业务层控制:业务层获取Connection并关闭自动提交,传给多个DAO方法,最后统一提交或回滚。

10.7 批处理与ORM框架

批处理

一次执行多个SQL语句,降低IO次数。一次批量约200条性能较好。

executeBatch() 返回 int[](每条语句影响行数),批量执行时应启动事务。

ORM框架基本原理

利用Java反射机制,动态创建对象、设置属性值。告知DAO对象SQL和对象类型,由DAO动态装配。

Hibernate通过XML配置文件建立类属性与表列的映射关系。

十一、上机操作实战

以下内容基于上机操作文档,围绕一个房间/建筑/合同管理系统(数据库 db_room)展开,包含1个工具类和4个核心方法,涵盖了考试上机题的主要题型。

11.1 DBUtil 数据库连接工具类必背

完整代码
package cn.edu.zucc.test; import java.sql.Connection; import java.sql.DriverManager;  public class DBUtil {     private static final String jdbcUrl = "jdbc:mysql://127.0.0.1:3306/db_room";     private static final String dbUser = "root";     private static final String dbPwd = "123456";      static {         try {             Class.forName("com.mysql.jdbc.Driver"); // 加载并注册MySQL驱动         } catch (ClassNotFoundException e) {             e.printStackTrace();         }     }      public static Connection getConnection() throws java.sql.SQLException {         return DriverManager.getConnection(jdbcUrl, dbUser, dbPwd);     } }
要点:静态代码块在类第一次加载时执行且只执行1次,用于加载驱动。DriverManager是Java自带的驱动管理类。

11.2 单条查询(PreparedStatement + ResultSet封装)

根据编号查询人员信息
String sql = "SELECT person_no, person_name, sex, age FROM tbl_person WHERE person_no = ?"; Connection conn = null; PreparedStatement pstmt = null; ResultSet rs = null; BeanPerson person = null;  try {     conn = DBUtil.getConnection();     pstmt = conn.prepareStatement(sql);     pstmt.setString(1, person_no);      // 给第1个 ? 赋值     rs = pstmt.executeQuery();     if (rs.next()) {                    // 单条用 if         person = new BeanPerson();         person.setPersonNo(rs.getString("person_no"));         person.setPersonName(rs.getString("person_name"));         person.setSex(rs.getString("sex"));         person.setAge(rs.getInt("age"));     } } finally {     // 关闭资源:rs → pstmt → conn     try { if(rs!=null) rs.close(); } catch(SQLException e) {}     try { if(pstmt!=null) pstmt.close(); } catch(SQLException e) {}     try { if(conn!=null) conn.close(); } catch(SQLException e) {} }

11.3 多层嵌套查询(分组聚合 + 子查询)

查总面积最大的建筑编号
-- SQL三层逻辑(从内到外): -- 最内层:按building_code分组,SUM(area)算每个建筑总面积 -- 中间层:MAX(total_area)求最大面积数值 -- 最外层:HAVING筛选"总面积=最大值"的建筑 SELECT building_code FROM tbl_room GROUP BY building_code HAVING SUM(area) = (     SELECT MAX(total_area) FROM (         SELECT SUM(area) AS total_area         FROM tbl_room GROUP BY building_code     ) AS temp )
固定规则:WHERE是分组前筛选行,HAVING是分组后筛选聚合结果。结果可能多行,用 while(rs.next()) 循环读取。

11.4 多表连接查询(JOIN + 分组计数)

统计每个建筑的合同数
-- 合同表只有room_no,需通过room_no关联房间表找到building_code SELECT r.building_code, COUNT(*) AS contract_count FROM tbl_contract c JOIN tbl_room r ON c.room_no = r.room_no GROUP BY r.building_code

结果存入 Map<String, Integer>(key=建筑编号,value=合同数)。

11.5 批量插入与事务处理必考

批量新增合同(事务四步)
String sql = "INSERT INTO tbl_contract(person_no, room_no, from_date, to_date, contract_amount) VALUES(?,?,?,?,?)"; Connection conn = null; PreparedStatement pstmt = null;  try {     conn = DBUtil.getConnection();     conn.setAutoCommit(false);  // 1. 关闭自动提交,开启事务      pstmt = conn.prepareStatement(sql);     for (Map.Entry entry : map.entrySet()) {         BeanContract c = entry.getValue();         pstmt.setString(1, c.getPersonNo());         pstmt.setString(2, c.getRoomNo());         // 日期转换:SimpleDateFormat解析 + Timestamp写入         pstmt.setTimestamp(3, new Timestamp(c.getFromDate().getTime()));         pstmt.setTimestamp(4, new Timestamp(c.getToDate().getTime()));         pstmt.setDouble(5, c.getAmount());         pstmt.executeUpdate();   // 2. 逐条执行     }      conn.commit();               // 3. 全部成功 → 提交 } catch (Exception e) {     if (conn != null) conn.rollback(); // 4. 出错 → 回滚     e.printStackTrace(); } finally {     try { if(pstmt!=null) pstmt.close(); } catch(SQLException e) {}     try { if(conn!=null) conn.close(); } catch(SQLException e) {} }
事务核心:把多条SQL绑成一个整体,要么全成功要么全失败,保证数据一致性。
日期处理SimpleDateFormat("yyyy-MM-dd") 解析字符串,Timestamp 写入数据库。

11.6 资源关闭万能模板必背

finally块关闭模板
finally {     try {         if(rs!=null) rs.close();      // 查询题才有rs         if(pstmt!=null) pstmt.close();         if(conn!=null) conn.close();     } catch (SQLException e) {         e.printStackTrace();     } }

关闭顺序:从小到大 rs → pstmt → conn。增删改题去掉第一行 rs 即可。

11.7 上机操作技能总结

8项核心实操技能
技能关键点
1. 编写DBUtil工具类加载驱动、获取连接
2. 单条查询PreparedStatement + ? + ResultSet封装到JavaBean
3. 聚合分组查询GROUP BY + HAVING + 多层子查询嵌套
4. 多表连接查询JOIN ON 关联多表
5. 批量插入与事务setAutoCommit(false) + 循环 + commit/rollback
6. 日期类型转换SimpleDateFormat解析 + Timestamp写入
7. 结果集封装单条用if(rs.next())+对象,多条用while+集合
8. 资源管理finally块按rs→pstmt→conn顺序关闭

十二、期末考试高频考点与真题分析

12.1 试卷题型分布必看

三套试卷题型对比
题型试卷1试卷2样卷
选择题--5题×2分=10分
填空题--5空×2分=10分
应用题(函数依赖与范式)12分12分10分
设计题(E-R图+转关系模式)8分14分-
SQL题5题×4分=20分6题×4分=24分20分
关系代数及查询优化10分10分-
总分50分60分50分

12.2 高频考点汇总必看

跨试卷高频考点
考点出现情况说明
函数依赖与范式判断3套均考给关系模式→画函数依赖图→求主码→判断范式→规范化到3NF
E-R图设计3套均考根据需求画E-R图,识别实体/联系/属性
E-R图转关系模式3套均考标主码和外码,1:1/1:N/M:N转换规则
SQL建表(含约束)3套均考CREATE TABLE,主码、外码、CHECK约束
SQL视图创建3套均考CREATE VIEW,含分组聚合
SQL删除(DELETE+子查询)3套均考删除无关联/无销售/无采购的数据
SQL更新(UPDATE+子查询)3套均考按条件修改单价/VIP/级别
SQL权限控制3套均考GRANT/REVOKE
关系代数(含除法)3套均考"出现在所有X的Y"必用除法
查询语法树与优化2套考画语法树并优化(选择/投影下推)
SQL插入(INSERT)2套考基本INSERT语句
封锁协议/死锁/恢复样卷考三级封锁协议、死锁解除、日志文件恢复
三级模式/数据独立性样卷考外模式/模式/内模式及映射

12.3 必背知识点速查

考前必背清单
知识点核心内容
ACID特性原子性、一致性、隔离性、持续性
先写日志原则必须先写日志文件,后写数据库(WAL)
三级封锁协议1级防丢失修改,2级+防读脏,3级+防不可重复读
两段锁协议可串行化的充分条件(非必要)
范式层级1NF→消除部分依赖→2NF→消除传递依赖→3NF→消除主属性依赖→BCNF
除运算查"出现在所有X的Y"类问题,求象集包含关系
双重NOT EXISTS实现全称量词:(∀x)P ≡ ¬(∃x(¬P))
WHERE vs HAVINGWHERE分组前筛选行,HAVING分组后筛选组
GRANT/REVOKEWITH GRANT OPTION允许传播权限,REVOKE级联收回
聚簇索引每表只能一个,物理顺序与索引顺序一致
JDBC流程Class.forName→getConnection→createStatement→executeQuery→处理ResultSet→关闭
PreparedStatement预编译、防SQL注入、?占位符
JDBC事务setAutoCommit(false)→执行→commit/rollback
资源关闭顺序rs → pstmt → conn(在finally中)
数据独立性逻辑独立性=外模式/模式映象,物理独立性=模式/内模式映象

12.4 解题方法论

函数依赖与范式题(5步法)
  1. 画函数依赖图:从语义推导所有函数依赖关系
  2. 求主码:找L类属性(只在左部),求闭包,验证是否=U
  3. 判断范式:检查部分依赖(→1NF)和传递依赖(→2NF)
  4. 说明原因:指出存在的部分/传递函数依赖
  5. 分解到3NF:按函数依赖分组,每组属性+决定属性组成新关系
SQL题解题策略
  • 建表题:注意PRIMARY KEY、FOREIGN KEY、CHECK约束的完整书写
  • 视图题:注意GROUP BY后SELECT只能出现分组属性和集函数
  • 删除/更新题:用 NOT IN + 子查询处理"没有关联记录"的情况
  • 权限题:GRANT ... TO ... [WITH GRANT OPTION] / REVOKE ... FROM ...
关系代数题解题策略
  • 除法题:识别"出现在所有...的..."句式,用 R÷S
  • 连接题:选择+投影+自然连接的组合
  • 语法树优化:选择条件下推到叶子节点,投影提前,连接最后

十三、PTA练习题精选

本章内容来自PTA平台题目集(159页),涵盖判断题、选择题、填空题和综合大题,是期末考试选择填空题的直接来源。

13.1 判断题精选必练

规范化理论
题目答案
项目的数据库设计必须完全符合范式要求T
范式的主要目的是提高查询效率F(消除冗余和异常)
任何二目关系(两个属性)属于3NFT
若R.A→R.B,R.B→R.C,则R.A→R.C(传递律)T
函数依赖集F的最小函数依赖集Fm不唯一T
若X→Y和Y→Z,且X、Y、Z为互不相同的单属性,则不存在X到Z的传递函数依赖T
E-R模型与数据库设计
题目答案
E-R图中用椭圆形表示属性T
数据库的概念模型不依赖于计算机硬件和DBMST
E-R图用于建立数据库的概念模型T
描述概念模型的有力工具是数据字典F(是E-R图)
概念结构设计最常采用的策略是自顶向下的方法F(自底向上)
物理设计阶段形成的是外模式F(内模式)
由概念设计进入逻辑设计时,多对多联系需转换成基本表T
主码查询一般使用索引扫描T
查询优化与索引
题目答案
查询优化策略由DBMS自动选择,不是由用户确定F
建立索引是为了提高检索速度T
连接运算尽可能先做是查询优化最重要最基本的策略T
查询优化总目标是选择有效策略求得关系表达式的值T
事务与恢复
题目答案
MySQL中COMMIT和ROLLBACK都是事务控制语句T
COMMIT后不能再ROLLBACKT
事务提交后对数据库的修改是永久的T
事务故障系统自动恢复,不必用户干预T
一级封锁协议可防止丢失修改T
三级封锁协议可防止丢失修改、不可重复读、读"脏"数据T
两段锁协议可保证可串行化T
两段锁协议可能发生死锁T
死锁可以通过预防和检测来解决T
活锁可以通过先来先服务策略避免T
静态转储不允许事务运行T
动态转储允许并发运行事务T
事务故障恢复用UNDOT
系统故障恢复需要UNDO和REDOT
安全性控制
题目答案
数据库中建立的索引不是越多越好T(索引越多越好是错的)
每行索引记录包含指向表中数据页的逻辑指针T
数据库加密提高安全性但降低效率T
强制存取控制安全级别高于自主存取控制T
数据库角色是被命名的一组权限集合T
所有授予的权力都可用REVOKE收回T
自主存取控制:用户可自主决定将权限授予何人T

13.2 选择题精选必练

规范化理论选择题
  • 规范化的主要目的:维护数据的一致性
  • 包含两个属性的关系模式一定满足:BCNF
  • 关系模式至少是:1NF
  • 消除部分函数依赖的1NF必定是:2NF
  • 在2NF基础上消除传递函数依赖,必定是:3NF
  • 若所有属性都是主属性,则R至少属于:3NF
  • 平凡函数依赖是指:Y是X的子集(如AB→A)
  • X→Y, Y→X 称为:互相函数依赖
E-R模型选择题
  • E-R图适用于建立:概念模型
  • 层次、网状和关系模型属于:逻辑模型
  • 概念设计中最常用的数据模型是:实体联系模型(E-R模型)
  • 概念结构设计常用方法:自底向上、自顶向下、逐步扩张(无"从外到内")
  • 3个实体型+3个M:N联系→转换为:6个关系(3实体+3联系)
  • 数据库设计六阶段顺序:需求分析→概念设计→逻辑设计→物理设计→实施→运行维护
事务选择题
  • DB并发操作导致的问题:丢失修改、不可重复读、读"脏"数据
  • 事务的持久性由DBMS的恢复机制实现
  • 事务的隔离性由并发控制机制实现
  • 事务的原子性由UNDO操作实现
  • 一级封锁协议:修改前加X锁,事务结束释放→防丢失修改
  • 二级封锁协议:一级+读前加S锁,读完释放→+防读脏数据
  • 三级封锁协议:一级+读前加S锁,事务结束释放→+防不可重复读
  • 死锁检测方法:等待图(有向图存在回路=死锁)

13.3 填空题精选必练

填空题汇总
题目答案
产生数据冗余和异常的两个重要原因是____和____函数依赖部分传递
若所有非主属性都完全函数依赖于主码,则R至少属于第____范式(2NF)
R有5个属性10个元组,S有3个属性100个元组,R×S有____个属性,____条元组81000
一个表最多____个聚集索引,____个非聚集索引1
创建非聚集索引的SQL语句CREATE NONCLUSTERED INDEX IDX1 ON employees(phone)

13.4 PTA综合大题类型汇总必看

PTA大题分值与类型
题型分值数量核心要求
E-R图设计5-18分10题画E-R图+转关系模式
关系模式分解8分9题函数依赖→候选码→范式→3NF分解
SQL查询6分多题多表连接查询(WHERE和JOIN两种写法)
PTA大题与期末考试的对应关系
PTA的关系模式分解题 → 期末考试应用题(12分)
PTA的E-R图设计题 → 期末考试设计题(8-14分)
PTA的SQL查询题 → 期末考试SQL题(每题4分)
PTA的判断/选择题 → 期末考试选择填空题(10-20分)

资料来源

  1. 上课课件:第4-15讲(关系数据库、SQL、范式、查询优化、事务、JDBC等),PDF格式 用户提供的课件文件
  2. 城市学院数据库原理期末考试试卷(2022-2023学年第一学期) 用户提供的试卷文件
  3. 城市学院数据库原理期末考试试卷(2023-2024学年第二学期) 用户提供的试卷文件
  4. 数据库概论样卷 用户提供的试卷文件
  5. 上机操作内容文档(房间/建筑/合同管理系统JDBC实操教程) 用户提供的文档
  6. 数据库PTA题目集(159页,涵盖规范化、E-R图、查询优化、安全性、事务管理等7大模块的判断题/选择题/填空题/综合大题) 用户提供的PDF文件