☰
openGauss数据库课设九实验全链路:建库建表、SQL控制与JDBC验收避坑
2026/10/27 20:00:23 网站建设 项目流程

简介:面向计算机科学与技术、软件工程专业学生及数据库课程学习者的《数据库系统原理实验》报告书,以郑州大学实验教学要求为背景,围绕 openGauss 环境组织九个实验,可作为课程实验、报告撰写与期末复盘的参考材料。压缩包内共 1 个 docx 文件,约 3.23MB,正文按实验项目分节编排,含实验目的、内容、类型、学时与主要仪器材料等栏目,并记录实验过程、问题更正和结果分析,便于直接查阅与编辑。已有 1525 人学习。内容从认识 DBMS 系统、创建数据库表与索引、交互式 SQL、创建视图,延伸到完整性控制、安全性控制、事务与并发控制、备份恢复及 JDBC 连接数据库,能帮助读者对照实验流程梳理知识点、理解 SQL 操作与数据库管理环节,并借鉴报告的组织结构和分析写法,适合需要完成课程实验或复习数据库系统原理的读者参考。

1. 从一份实验报告说起:数据库课设真正要交付什么

数据库课的实验报告,很多人写成了命令截图合集:装完 openGauss,敲几条 SQL,截几张图,交上去。等到验收被问“你这个外键为什么要用表级约束而不是列级约束”“索引建了之后查询计划变没变”,就答不上来了。这份九实验的《数据库系统原理实验》报告书,解决的正是这个问题:它把认识 DBMS、建库建表建索引、交互式 SQL、视图、完整性控制、安全性控制、事务与并发、备份恢复、JDBC 连接串成一条完整链路,每个实验都有目的、内容、学时、仪器和结果分析的位置。适合两类人:正在赶数据库课设或毕设前期验证的学生,以及想把一套能跑通的数据库实践方案拿来改的从业者。我要讲的不是“报告怎么写好看”,而是这九个实验背后那条从建库到应用连接的技术主线怎么落地、哪里会翻车、验收怎么看。

2. 实验平台与环境设计:openGauss 的安装选型与连接方式

2.1 三种安装模式的取舍

原报告列了三种路子:云上安装、虚拟机一键安装、先装 openEuler 再装 openGauss。这不是凑字数,是三条成本完全不同的路径,选错会直接影响后面八个实验能不能顺利做完。

云上安装最省事,环境由平台准备好,但网络策略、端口开放、客户端工具版本都要对齐,一旦连不上,排查链条长,对第一次接触 DBMS 的人不友好。一键安装脚本在虚拟机上跑,省去操作系统层依赖的手工配置,适合时间紧、只想尽快看到 gsql 提示符的场景。先装 openEuler 再装数据库,步骤最多,但每一步都是可见的:依赖包、用户组、目录权限、环境变量,出了问题能定位到具体一层。

我一般建议课设这种有固定学时的场景走第二条,把第三条留作备用。原因很实在:实验二之后要频繁创建表空间、切数据库、建模式,环境必须是可反复折腾的。云上一旦误操作锁了账号或者占满配额,恢复成本比本地虚拟机高得多;而纯手工安装,如果对 Linux 权限模型不熟,光 omm 用户的家目录权限就能耗掉两个小时。

环境确定之后,几件事要在实验一一次做对:操作系统统一(Windows 客户端加 openEuler 服务端,或者纯 openEuler),端口记牢,默认库名记牢。报告里写的 26000 是主节点端口,postgres 是安装后默认生成的数据库。这两个值后面每个实验都要用,写进报告的实验环境说明里,比事后翻笔记靠谱。

2.2 连接链路:从 su 到 gsql

登录数据库这一步,报告给了标准动作,值得原样保留在报告里,因为它把“服务有没有起来”和“客户端能不能连”拆成了两段,排查时特别好用。

# 切换至数据库安装用户,openGauss 不允许 root 直接连库 su - omm # 启动数据库服务,-t 表示对实例做操作 gs_om -t start # 连接默认库 postgres,-p 指定主节点端口,-r 开启回显 gsql -d postgres -p 26000 -r

这三行的顺序不能乱。su - omm里的减号是关键,它让环境变量一并切换过去,少了这个减号,后面 gsql 很可能提示找不到命令或连不上实例。gs_om -t start是实例级操作,服务没起时直接连库只会得到连接被拒绝,这时候看服务状态比反复改连接串有用。-r的作用是回显执行的 SQL,写实验报告时截图更清楚,也方便对照输出分析结果。

连接成功后再做实验一的两件正事:建库用户、建数据库。默认只有安装时创建的管理员能访问初始库,所以要新建一个业务用户,用它去连接、建表,把“管理员”和“业务操作者”分开。这个习惯看似多余,但它直接对应实验六的安全性控制——权限体系是建在用户和角色上的,实验一不建用户,实验六就没有实验对象。

提示:每次重启虚拟机后先确认服务状态再连接,别把“服务没启动”误判成“密码错了”。

3. 数据库对象设计:从表空间到表、约束与索引的建库主线

3.1 表空间、数据库、模式的三层划分

实验二真正要建立的认知是层次:表空间是物理存储的划分,数据库是逻辑隔离的单位,模式是库内的命名空间。报告里用“文件夹”类比表空间,这个类比在课设阶段够用,但要知道它的边界——一个数据文件只能属于一个表空间,一个表空间可以容纳多个数据文件。

-- 建表空间,relative location 指向一个已存在的空目录 CREATE TABLESPACE tpcds_local RELATIVE LOCATION 'tablespace/tablespace_1'; -- 建库时显式指定表空间,避免全部堆在默认位置 CREATE DATABASE db_sc WITH TABLESPACE = tpcds_local; -- 改名,注意这里是 ALTER DATABASE,报告正文里拼写有笔误,照抄会报语法错误 ALTER DATABASE db_sc RENAME TO db_school; -- 切库,gsql 的元命令,不是 SQL \c db_school

四个动作对应四件事:空间先划出来,库挂在指定空间上,名字可以改,操作前必须切到目标库。第三条最容易翻车,ALTER DATABAE这种拼写错误在报告里出现不止一处,抄进自己的报告只是小事,真正的问题是它会让人误以为语句本身有问题,绕很久。

模式的创建与级联删除也要在这一节做掉。报告里CREATE SCHEMA book_eg之后建 Teachers、Departments,然后DROP SCHEMA book_eg CASCADE。CASCADE 的含义是把模式下的对象一起删掉,不带 CASCADE 时只要模式非空就删不动。这个细节在验收时经常被追问,因为它直接体现对“模式是对象的容器”这一点的理解。

3.2 六张表的结构与约束设计

报告围绕教师、院系、学生、课程、选课、教学六张表展开,这是一个典型的教务模型。设计上有两处值得说清楚,因为它们是后面实验五完整性控制的伏笔。

第一处是建表顺序与外键方向。Teachers 先建,Departments 引用 Teachers 的 Tno 作为 Dheadno 外键;Students 引用 Departments 的 Dno。也就是说,系主任必须是教师表里的人,学生必须属于某个系。这种自引用式的设计在真实系统里很常见,但它带来一个建表顺序问题:必须先有 Teachers 才能建 Departments,先有 Departments 才能建 Students。如果建表时顺序反了,会直接报外键引用对象不存在。

第二处是列级约束和表级约束的区别。报告里专门辨析过:列级约束写在列定义之后,表级约束写在所有列定义之后、用逗号分隔,并且必须指明约束作用的列。两者能力不同——非空和默认值只能做成列级,涉及多列或需要命名时用表级。看这段建表语句:

CREATE TABLE Teachers ( Tno CHAR(20) PRIMARY KEY, -- 主键,列级 Tname CHAR(20) NOT NULL, -- 非空,只能列级 Sex CHAR(20) CHECK (Sex = '男' OR Sex = '女'), -- 取值检查,列级 Birthday DATE, Title CHAR(20), Dno CHAR(20) ); CREATE TABLE Departments ( Dno CHAR(20) PRIMARY KEY, Dname CHAR(20), Dheadno CHAR(20), FOREIGN KEY (Dheadno) REFERENCES Teachers(Tno) -- 外键,表级 );

外键放在表级不只是写法问题。列级外键在语法上多数场景也能写,但一旦需要给约束命名、或者一个外键涉及多列,就只能走表级。报告里提到“由于关系中存在相互参照,需要通过修改表添加表级约束”,说的就是这种场景:表已经建好了,后来发现要补一个外键,只能 ALTER TABLE 加。

学生表和课程表的类型选择也有讲究。Period 和 Credit 用 SMALLINT,报告里辨析了无符号 SMALLINT 的范围是 0 到 65535,INT 是四字节、范围更大。学时和学分不可能超过几百,用 SMALLINT 完全够,字段宽度选小一点在页内能放更多行。这类“够用就好”的判断,写进报告的结果分析里,比单纯贴建表语句有说服力。

3.3 索引的建立与删除

索引这一节,报告的落点是“在 Students 的 Dno 上建索引 Student_Dept”,然后用\di查看。这里有两点必须在报告里点出来,否则实验等于没做。

第一,主键会自动建索引。报告里明确写了“DBMS 自动为主码建立索引”,所以建表之后\di已经能看到主键索引,不需要手工再建。这解释了为什么手工索引只建在外键列 Dno 上——外键列不自动建索引,而按系查学生是最常见的查询之一。

第二,索引不是越多越好。索引加速检索,但每次插入、删除、更新都要同步维护索引结构,写多读少的表上堆索引会拖慢写入。课设阶段数据量小,看不出差别,但报告的分析部分如果只写“索引能加快查询”,就少了该有的判断。我会补一句:判断该不该建,先看这条列会不会出现在 WHERE 和连接条件里,再考虑写操作频率。

-- 在外键列上建索引,命名体现表名和列名 CREATE INDEX Student_Dept ON Students(Dno); -- 删除索引的写法,对照实验要求保留 DROP INDEX Student_Dept;

\di是元命令,查的是当前库的索引列表;\d+ tablename查的是单表的结构、约束和索引,两者搭配用,报告里的截图信息才完整。

4. 查询与控制类实验的实现:SQL、视图、完整性与安全性

4.1 交互式 SQL 与视图层

实验三是交互式 SQL,实验四是视图。这两个实验放一起看,逻辑是连贯的:先是直接对表做增删改查,然后引入视图做一层抽象。查询部分要覆盖单表条件查询、多表连接、聚合分组、子查询这几类,报告的写法通常是把教材上的例题在 openGauss 里跑一遍,截图加分析。

视图的价值要在实验四里说清楚,否则很容易写成“CREATE VIEW 的语法演示”。视图本质上是一条被命名的查询,它能做三件事:简化复杂连接、限制可见列、给不同用户不同的数据视角。第三条和实验六的安全性控制是接的——把视图的查询权限授给某个用户,他就只能看到视图暴露的那部分列和行。

-- 建一个学生选课概览视图,隐藏敏感字段,只暴露必要信息 CREATE VIEW v_student_course AS SELECT s.Sno, s.Sname, c.Cname, sc.Grade FROM Students s JOIN SC sc ON s.Sno = sc.Sno JOIN Courses c ON c.Cno = sc.Cno; -- 查视图与查表写法一致,但视图重新执行的是底层查询 SELECT * FROM v_student_course WHERE Grade >= 90;

要注意的是,视图查询不是缓存,每次查都回到底层表执行。数据量大的场景下,一个多层嵌套的视图可能比直查还慢,所以在报告的分析里应该提一句:视图优先用于简化访问和权限控制,不要指望它提升性能。

4.2 完整性控制的三个层次

实验五是完整性控制,这块是课设里最容易写虚的。实体完整性靠主键,参照完整性靠外键,用户定义完整性靠 CHECK、NOT NULL、DEFAULT,这是三个层次。报告里对约束的分类辨析已经比较细,需要补充的是“约束被违反时会发生什么”。

拿外键举例,向 SC 表插入一条 Sno 在学生表里不存在的记录,数据库会直接拒绝,报违反外键约束。这个行为要截图,并且要说明:拒绝插入不是错误,是保护。反过来,删除 Departments 里某个系而 Students 里还有该系学生时,删除同样会被拒绝,除非先处理从表数据或者使用级联。这一正一反两个方向的操作,才是完整性控制的完整验证。

阶梯式的验证顺序是:先插合法数据,再插违反 NOT NULL 的、违反 CHECK 的、违反主键唯一性的、违反外键的,每类一条,记录报错信息。报告的结果分析里写清楚“哪条约束拦住了哪类脏数据”,比罗列约束语法有分量得多。

4.3 安全性控制:用户、角色与授权

实验六做安全性控制,对象是用户和角色。报告里那段辨析写得不错:用户是具体账户,角色是一类账户的权限集合,把角色授予用户,用户就获得该角色包含的全部权限,人员调岗时换个角色就行,不用逐个改权限。这个模型在实际系统里的价值,比实验本身的命令更值得写进报告。

落地动作是三步:建用户、建角色、授权。

-- 建业务用户并设置密码 CREATE USER app_reader WITH PASSWORD 'Read@12345'; -- 建角色,把一组只读权限打包 CREATE ROLE role_readonly; -- 把角色授予用户,用户继承角色的权限 GRANT role_readonly TO app_reader; -- 授予具体对象的查询权限给角色,注意不是直接给用户 GRANT SELECT ON Students, Courses TO role_readonly; -- 收回权限,REVOKE 是 GRANT 的逆操作 REVOKE SELECT ON Courses FROM role_readonly;

授权完要验证:用新用户连接,查有权限的表能出结果,查没权限的表被拒绝。这一步很多报告省略了,只贴 GRANT 语句,等于没证明权限真的生效。验证时用\c - username切换用户,比退出重连省事。

注意:权限授予对象是角色而不是用户,这个习惯在用户量上来之后差别巨大。课设里就两三个用户看不出好处,但报告里体现这个设计意识,答辩时是加分项。

实验七的事务与并发控制,落点在事务的 ACID 特性验证上:开事务、做几条修改、ROLLBACK 看数据回滚,再开事务 COMMIT 看数据落盘。并发部分通常演示两个会话同时更新同一行导致的锁等待,或者用不同隔离级别观察脏读、不可重复读的差异。这部分截图要多会话窗口,报告里要标明每个窗口执行的是哪一步。

5. 避坑与常见问题:实验环境里最容易翻车的五处

5.1 服务没起来就怀疑连接串

现象:gsql 连接报拒绝,反复检查端口和库名都不对。 原因:实例没启动,或者启动到一半失败。gs_om -t start返回成功不代表实例可用,日志里可能还有错误。 解决:先gs_om -t status看实例状态,再翻实例目录下的日志,确认是端口占用、目录权限还是数据文件问题,最后才动连接参数。

5.2 建表顺序违反外键引用

现象:建 Departments 时报引用的表不存在,或者插入系数据时报教师不存在。 原因:外键要求被引用表和被引用记录先存在。Teachers 先于 Departments、Departments 先于 Students,这个顺序是模型决定的。 解决:按依赖顺序建表;确需后补的约束用 ALTER TABLE 加。批量插入数据时同样要按顺序,先教师、再院系、再学生。

5.3 抄报告里的拼写错误

现象:语句照着报告敲,报语法错误,但看着一模一样。 原因:原始报告里存在ALTER DATABAE、create databse这类笔误,还有全角空格和中文标点混入。 解决:语句先在 gsql 里跑通再往报告里贴,报告里的每一条 SQL 都应该是实际执行过的。中文标点这个坑尤其隐蔽,引号和分号最容易中招。

5.4 用 root 直接连库

现象:gsql 提示权限不足或连接失败。 原因:openGauss 出于安全考虑不允许 root 直接连接,必须切到安装用户。 解决:su - omm切环境,注意减号。切完用whoami确认身份,再执行 gsql。

5.5 备份恢复只做备份没做恢复

现象:实验八备份文件生成了,但恢复环节跳过或者恢复到一个已存在的库上失败。 原因:恢复要求目标库状态干净,库已存在时直接恢复会冲突;备份前没确认数据量,恢复后也没比对。 解决:备份前记录关键表的行数,恢复前删掉或改名目标库,恢复后再查一次行数比对。备份不验证恢复,等于没备份,这个习惯比实验本身重要。

6. 验收与答辩:把九个实验讲成一条线的方法

验收现场被问倒,多半不是因为某个命令不会写,而是没把九个实验串起来。我的做法是准备一条“数据流”主线,从建库讲到应用连接,每个实验都是这条线上的一个环节。

具体怎么练:把报告里的截图按主线重排一遍,不看文字只看图,能不能讲出“这一步为下一步准备了什么”。实验一建了用户和库,实验二才能建表和索引;实验二的外键关系,实验五才有完整性可验证;实验四的视图,实验六才能演示基于视图的权限控制;实验七的事务保证,实验八的备份恢复才有意义;实验九用 JDBC 把前面所有对象从应用层访问一遍,形成闭环。这条线讲通了,任何单点追问都能落回上下文。

答辩常问的问题集中在三类,我整理成一张对照表,按这个准备基本够用:

追问类型典型问题回答要点
设计决策为什么外键用表级约束涉及命名或后续 ALTER 补充,且多列外键只能表级
行为验证违反约束时数据库怎么表现直接拒绝写入并报错,这是保护不是故障,附截图
性能与取舍索引是不是越多越好加速读、拖慢写,按查询条件和写频率权衡
环境排查连不上库先查什么先服务状态、再用户环境、最后连接参数

实验九的 JDBC 部分单独说一下,因为它最容易被草率处理。验收时如果能现场跑一段连接代码、查出前面建的表里的数据,说服力远大于截图。

// 加载驱动后建立连接,URL 里分别指定库名和端口 Class.forName("org.opengauss.Driver"); String url = "jdbc:opengauss://127.0.0.1:26000/db_school"; try (Connection conn = DriverManager.getConnection(url, "app_reader", "Read@12345"); Statement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery("SELECT Sno, Sname FROM Students")) { while (rs.next()) { System.out.println(rs.getString("Sno") + "\t" + rs.getString("Sname")); } }

这段代码的关键不在语法,在于它用的是实验一建的业务用户、实验二建的库和表,一次运行就把整条链路验证了。URL 的三个部分——地址、端口、库名——任何一处和前面实验对不上,都会连不上,这本身就是一次很好的自查。

带过几轮实验之后我养成一个习惯:报告写完先不看内容,只看目录页的九个实验名,逐个问自己“这个实验的输入来自哪、输出喂给了谁”,答不上来的那个实验就一定存在没想清楚的地方,回去补。这个方法比反复检查格式有用得多。希望帮到你。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询