
简介这份中南大学数据库试题资料面向高校数据库课程学习者与备考学生聚焦数据库原理的系统复习与自测。内容覆盖DBMS基础、数据管理三阶段、三级模式结构、DDL/DML/DCL语言组成、ER模型与键约束、关系模型及关系代数、SQL与索引、数据库保护安全性、完整性、故障恢复、并发控制与ACID、关系数据库设计理论函数依赖、1NF至3NF规范化、模式分解以及数据库应用设计六步骤并附有选择题、填空题、术语解释与简答题等试卷题型便于对照知识点查漏补缺。资源包为1个doc文档约164KB结构紧凑适合打印或电子阅读。目前已有351人学习下载可作为课程复习总纲与考前自测的参考材料。1. 中南大学数据库试题从一套卷子看数据库课程的真实考核边界如果你正在搜「中南大学数据库试题」大概率不是单纯想找一份卷子对答案而是想搞清楚这所学校的数据库课程到底考什么、考到什么深度、自己复习的方向对不对。我当年帮几个学弟做过考前突击翻过他们手里的历年题也自己按考点复现过一遍建库建表、写 SQL、推范式、画 ER 图的全过程。结论很直接中南大学数据库试题的骨架基本围绕关系模型、SQL 语句、范式分解、事务与并发控制这四块展开题型稳定但每块都有几个反复出现的「送命题」。这套题不是靠背概念能过的它逼你真的动手写 SQL、真的会判断一个关系到底属于第几范式。适合正在备考的学生也适合想用一套真实考题反向梳理数据库知识体系的从业者。下面我按「考什么 → 怎么练 → 坑在哪」的顺序把这套题的复习路径拆开讲。2. 中南大学数据库试题的四大考点与对应复习路径2.1 关系模型与 ER 图从题目描述到表结构的完整推导中南大学数据库试题里关系模型这块很少直接问定义而是给你一段业务描述让你画 ER 图、再转成关系模式最后标出主键和外键。常见场景是「学生选课」「图书借阅」「订单管理」这三类。我一般会按下面的顺序推第一步从描述里圈出实体。实体通常是名词比如「学生」「课程」「教师」。第二步找实体之间的联系注意一对多、多对多、一对一这三种。多对多必须单独建一张联系表这是最容易丢分的地方。第三步把 ER 图转成关系模式每个实体一张表多对多联系一张表一对多把「一」方的主键放到「多」方做外键。下面是我用 Python 的sqlite3快速验证表结构是否合理的一段代码考试时手写复习时用代码跑一遍能立刻发现主键冲突或外键指向错误import sqlite3 conn sqlite3.connect(:memory:) cur conn.cursor() # 学生表学号为主键 cur.execute(CREATE TABLE student ( sno TEXT PRIMARY KEY, sname TEXT NOT NULL, major TEXT )) # 课程表课程号为主键 cur.execute(CREATE TABLE course ( cno TEXT PRIMARY KEY, cname TEXT NOT NULL, credit INTEGER CHECK(credit 0) )) # 选课表多对多联系联合主键 cur.execute(CREATE TABLE sc ( sno TEXT, cno TEXT, grade REAL, PRIMARY KEY (sno, cno), FOREIGN KEY (sno) REFERENCES student(sno), FOREIGN KEY (cno) REFERENCES course(cno) )) conn.commit() print(表结构创建成功主外键约束生效) conn.close()这段代码的逻辑说明student和course是实体表sc是联系表。PRIMARY KEY (sno, cno)保证同一个学生同一门课只有一条选课记录这是多对多联系的标准写法。参数上CHECK(credit 0)是考试里常被忽略的完整性约束写上去能体现你对域完整性的理解。外键的REFERENCES必须指向已存在的主键顺序不能反。跑通这段代码ER 图转关系模式这一步基本就不会翻车。2.2 SQL 语句从单表查询到嵌套与连接的得分要点SQL 是中南大学数据库试题里分值最重的一块通常占 40% 左右。题型从简单的SELECT ... WHERE到多表连接、嵌套查询、GROUP BY ... HAVING都有。我统计过出现频率最高的三类是查平均分最高的学生、查选修了某门课全部学生的课程、查没有选课的学生。这三类分别对应聚合、除法、外连接。复习时不要只背语法要按「先确定结果列 → 再确定涉及表 → 最后写连接和过滤」的顺序写。下面这段 SQL 覆盖了连接、聚合和嵌套是我用来练手的模板-- 查询每个学生的选课门数和平均分按平均分降序 SELECT s.sno, s.sname, COUNT(sc.cno) AS course_count, AVG(sc.grade) AS avg_grade FROM student s LEFT JOIN sc ON s.sno sc.sno GROUP BY s.sno, s.sname HAVING COUNT(sc.cno) 1 ORDER BY avg_grade DESC; -- 查询选修了全部课程的学生学号除法实现 SELECT sno FROM sc GROUP BY sno HAVING COUNT(DISTINCT cno) (SELECT COUNT(*) FROM course);逻辑说明第一段用LEFT JOIN保证没选课的学生也出现COUNT(sc.cno)只统计非空值所以没选课的学生计数为 0。GROUP BY必须包含sno和sname因为sname不是聚合列。第二段是经典的「除法」写法COUNT(DISTINCT cno)等于课程总数就说明这个学生选了全部课程。参数上DISTINCT不能省否则同一门课重修两次会被算成两门。HAVING和WHERE的区别是考试高频考点WHERE在分组前过滤行HAVING在分组后过滤组。2.3 范式判断与分解3NF 和 BCNF 的手工推导方法范式这块中南大学数据库试题喜欢给一个关系模式加一组函数依赖让你判断最高属于第几范式然后分解到 3NF 或 BCNF。很多人在这里丢分是因为只背了定义没掌握推导顺序。我一般按这个流程走先求候选键。把函数依赖画成有向图入度为 0 的属性一定在候选键里然后看闭包能不能推出全部属性。再判断范式如果每个非主属性都完全依赖于候选键就是 2NF如果不存在传递依赖就是 3NF如果每个决定因素都包含候选键就是 BCNF。举个例子关系R(A, B, C, D)依赖A→B, B→C, A→D。候选键是A。A→B→C存在传递依赖所以不是 3NF最高是 2NF。分解到 3NF 就是R1(A, B, D)和R2(B, C)。考试时建议把每一步的闭包写出来不要跳步。下面这个表格是我整理的判断速查范式判断条件常见错误1NF每个属性不可再分把多值属性塞进一个字段2NF非主属性完全依赖候选键忽略联合主键的部分依赖3NF不存在非主属性对候选键的传递依赖把传递依赖当成完全依赖BCNF每个决定因素都包含候选键只检查非主属性漏掉主属性参数说明判断 2NF 时如果候选键是单属性那它自动满足 2NF不用再查部分依赖。判断 BCNF 时要检查所有函数依赖的决定因素包括主属性之间的依赖。这一步是很多人后悔药都来不及吃的地方。2.4 事务与并发ACID 在试题里怎么考事务这块中南大学数据库试题通常考两类一是给一个并发调度让你判断是否可串行化二是问某个隔离级别下会出现什么异常。常见异常有脏读、不可重复读、幻读。我一般用「两段锁协议」来判断可串行化如果调度里每个事务的加锁和解锁都分两个阶段就是可串行化的。下面这段 Python 用sqlite3模拟两个事务并发更新同一行观察锁行为import sqlite3 import threading def transaction_a(): conn sqlite3.connect(test.db, isolation_levelNone) cur conn.cursor() cur.execute(BEGIN EXCLUSIVE) cur.execute(UPDATE account SET balance balance - 100 WHERE id 1) print(事务A已扣款等待...) conn.commit() conn.close() def transaction_b(): conn sqlite3.connect(test.db, isolation_levelNone) cur conn.cursor() cur.execute(BEGIN EXCLUSIVE) cur.execute(UPDATE account SET balance balance 100 WHERE id 1) print(事务B已入账) conn.commit() conn.close() # 先建表并初始化 conn sqlite3.connect(test.db) conn.execute(CREATE TABLE IF NOT EXISTS account (id INTEGER PRIMARY KEY, balance REAL)) conn.execute(INSERT OR IGNORE INTO account VALUES (1, 1000)) conn.commit() conn.close() t1 threading.Thread(targettransaction_a) t2 threading.Thread(targettransaction_b) t1.start() t1.join() t2.start() t2.join()逻辑说明BEGIN EXCLUSIVE是排他锁事务 A 提交前事务 B 会被阻塞这样保证不会出现脏读。参数上isolation_levelNone表示手动控制事务否则sqlite3会自动提交。考试里如果问「什么隔离级别能避免脏读」答案是读已提交及以上。如果问「什么级别能避免幻读」答案是串行化。注意sqlite3的默认隔离级别和标准 SQL 有差异复习时以教材定义为准。3. 避坑中南大学数据库试题里最容易翻车的五个点3.1 现象SQL 写对了但结果多出重复行原因多表连接时没有意识到笛卡尔积或者GROUP BY漏了列。比如student和sc连接后一个学生选了三门课就会出现三行如果再用COUNT(*)统计学生数就会偏大。解决统计学生数用COUNT(DISTINCT sno)或者先对sc做子查询再连接。3.2 现象范式判断写成 3NF 但实际是 2NF原因只看了非主属性对候选键的依赖没检查联合主键下的部分依赖。比如R(学号, 课程号, 成绩, 课程名)候选键是(学号, 课程号)但课程号→课程名是部分依赖所以最高是 2NF。解决先列出所有候选键再逐个检查非主属性是否完全依赖。3.3 现象事务调度判断可串行化时漏看冲突操作原因只看了读写顺序没看冲突操作对。两个事务如果操作不同数据项即使顺序交叉也不冲突。解决画出优先图如果图中有环就不可串行化无环就可串行化。3.4 现象ER 图转关系模式时多对多联系忘了建表原因把多对多联系当成属性塞进实体表。比如「学生选课」把课程号塞进学生表导致一个学生只能选一门课。解决多对多必须单独建联系表主键是两个实体主键的联合。3.5 现象写 SQL 时NULL值导致聚合结果偏差原因COUNT(列名)不统计NULL但COUNT(*)统计所有行。如果某列有NULL两者结果不同。解决明确题目要统计的是行数还是非空值数AVG也会忽略NULL必要时用COALESCE补默认值。4. 用真题反推复习节奏三周把中南大学数据库试题吃透4.1 第一周按考点建索引把错题归类第一周不要急着刷整套卷子先把考点拆开。我一般把中南大学数据库试题分成四类ER 与关系模型、SQL、范式、事务。每类找 5 道题做完后把错题按「概念不清」「语法不熟」「粗心」三种原因归类。概念不清的回去翻教材对应章节语法不熟的直接敲代码验证粗心的在题号旁标红。这一周的目标是让每个考点都有对应的错题记录。4.2 第二周限时模拟训练手写 SQL 的速度第二周开始整套限时做按考试时间打八折。手写 SQL 和键盘敲差别很大建议用白纸写写完再敲进sqlite3或 MySQL 验证。验证时重点看三处连接条件是否漏写、GROUP BY是否完整、NULL处理是否正确。这一周至少做三套每套做完把耗时超过 5 分钟的题目标记出来单独再练。4.3 第三周只刷错题和范式推导第三周不再做新题把前两周的错题重做一遍。范式推导每天手推 3 道要求写出候选键、闭包、判断依据、分解结果。事务调度题每天画 2 个优先图。这一周的目标是让范式判断和事务调度变成条件反射看到题就能下笔。4.4 考前两天把易忘参数和语法抄在一张纸上考前两天不要再刷新题把容易忘的点抄在一张 A4 纸上。比如HAVING和WHERE的区别、COUNT(DISTINCT)的用法、3NF 和 BCNF 的判断条件、两段锁协议的两个阶段。这张纸进考场前看一遍进考场后先默写在草稿纸上。我当年靠这个习惯SQL 和范式部分基本没丢分。提示中南大学数据库试题的题量通常较大手写 SQL 要留足时间建议先做范式判断和 ER 图最后写 SQL避免前面卡住后面来不及。5. 从试题到工程把范式判断写成可复用的检查脚本考完试不等于结束。我后来把范式判断的逻辑写成了一个 Python 脚本输入函数依赖集合自动输出候选键和最高范式。这个脚本帮我省了很多手工推导的时间也让我对函数依赖闭包的理解更深了一层。from itertools import combinations def closure(attrs, fds): 求属性集 attrs 在函数依赖集 fds 下的闭包 result set(attrs) changed True while changed: changed False for left, right in fds: if set(left).issubset(result) and not set(right).issubset(result): result | set(right) changed True return result def find_candidate_keys(all_attrs, fds): 暴力搜索候选键闭包等于全部属性的最小属性集 all_attrs set(all_attrs) keys [] for r in range(1, len(all_attrs) 1): for combo in combinations(all_attrs, r): if closure(combo, fds) all_attrs: # 检查最小性去掉任一属性后闭包不再等于全部属性 if not any(closure(set(c) - {a}, fds) all_attrs for c in [combo] for a in combo): keys.append(set(combo)) return keys # 示例R(A,B,C,D)依赖 A-B, B-C, A-D attrs [A, B, C, D] fds [(A, B), (B, C), (A, D)] keys find_candidate_keys(attrs, fds) print(候选键:, keys) print(A的闭包:, closure([A], fds))逻辑说明closure函数不断扫描函数依赖只要左边被当前属性集包含就把右边并进来直到不再变化。find_candidate_keys从单属性开始枚举找到闭包等于全部属性的组合后再检查最小性。参数上fds用元组列表表示左边和右边都是字符串。这个脚本对考试里的范式题同样适用输入依赖就能验证自己的手工推导。我一般用它来检查 3NF 分解是否保持依赖比手推快很多。最后说一个我自己的习惯每次复习数据库我都会先建一个test.db把题目里的表全部建出来插几条数据然后把 SQL 跑一遍。跑不通就说明理解有偏差跑通了再看结果对不对。这个习惯让我从「背 SQL」变成「写 SQL」考试时手写也更有底气。希望帮到你。本文还有配套的精品资源点击获取