☰
Oracle数据库课程设计:学生考勤系统完整落地链路与二次开发指南
2026/10/18 2:15:58 网站建设 项目流程

简介:这份Oracle数据库课程设计资料面向学习数据库管理与开发的学生及IT从业者,以“学生考勤系统”为完整案例,帮助读者掌握从需求分析到数据库落地的全流程设计方法。内容涵盖系统背景分析、多角色用户需求(学生、任课老师、班主任、院系领导、学校领导、系统管理员)、请假与考勤及后台管理三大功能模块划分,并给出E-R模型、数据字典、数据库表逻辑结构设计,以及表空间创建、建表与触发器、存储过程等数据库对象的实现思路,同时涉及性能优化、安全性设置与备份恢复策略。资源包共1个doc文件,约227KB,为课程设计报告文档,结构完整、目录清晰,可直接作为课程设计参考模板或答辩材料。目前已有965人学习下载,适合需要完成数据库课程设计、梳理设计文档或借鉴考勤系统建模思路的读者参考使用。

1. 学生考勤系统:一份 Oracle 课程设计里的完整数据库落地链路

如果你手头正躺着一份 Oracle 数据库课程设计,打开一看是“学生考勤系统”,别急着把它当成一份交完就删的作业。这份东西其实是一条完整的数据库落地链路:从需求分析、E-R 建模、数据字典,到表空间设计、建表语句、存储过程、视图和触发器,全都有。它解决的是一个很具体的问题——高校里学生请假要跑好几个办公室、任课老师看不到请假记录、班主任查不全出勤、院系领导拿不到汇总数据。这套设计用六类用户角色(学生、任课老师、班主任、院系领导、学校领导、系统管理员)把权限和数据范围切得清清楚楚,再用 Oracle 的表空间、约束、存储过程把这些规则固化到数据库端。适合谁看?正在做数据库课设的学生、想补 Oracle 工程化实践的开发者,以及需要一套现成考勤数据模型做二次开发的人。

2. 需求到模型:六类用户怎么映射成十二张表

2.1 角色权限拆解与功能模块划分

这套系统最值得先看的是角色划分,因为它直接决定了后面表结构和查询权限的设计。六类用户不是随便列的,每一类对应一组明确的数据可见范围和操作权限。

学生:只能看自己的出勤记录和请假进展,能提交请假申请,能改自己的密码。任课老师:管理自己所教班级的出勤记录,系统会根据请假系统自动判定学生最终出勤状态。班主任:审批本班学生的请假,查看本班所有课程的出勤统计。院系领导:审批超过三天的请假,查看本院系所有学生的出勤信息。学校领导:只查看全校出勤汇总,不参与审批。系统管理员:维护院系、专业、班级、课程、课表、用户等基础数据。

功能上切成三大模块:请假系统、考勤系统、后台管理。请假系统的核心是一条审批链——学生提交,班主任审批,超过三天再流转到院系领导。考勤系统的核心是任课老师录入出勤状态,系统结合请假记录自动判定最终结果。后台管理负责所有基础数据的动态更新,因为每学年课表在变、班主任在变、学生也在变。

注意:角色越多,权限表越容易设计成一张大宽表。这里按角色拆成独立表(admin、student、teacher、classteacher、collegeleader、schoolleader),每张表只存该角色特有的字段,公共字段如姓名、性别不抽公共表,是为了让课程设计的逻辑更直白,查权限时不用多一层关联。

2.2 E-R 模型里的实体与关系

E-R 模型部分把实体和关系列得很清楚。核心实体有:学院、专业、班级、学生、教师、班主任、院系领导、学校领导、课程、请假条、考勤记录。关系上,学生属于班级、班级属于专业、专业属于学院,这是一条层级链;教师授课、班级开设课程、班主任管理班级、院系领导聘请班主任,这些是多对一或一对多关系;请假条关联学生和班级,考勤记录关联学生、教师和课程。

这里有一个设计上的取舍值得注意:请假条和考勤记录是分开的两张表,没有合并。原因是它们的生命周期不同——请假条先产生,审批状态会变化;考勤记录后产生,状态相对固定。分开之后,任课老师录入考勤时可以通过学生学号和课程号去关联请假表,自动判断该学生当时是否处于已批准的请假状态。

2.3 数据字典与逻辑结构设计的对应关系

数据字典部分定义了每个实体的属性组合。比如学生信息 = 学号 + 姓名 + 性别 + 专业 + 院系 + 班级;请假条信息 = 请假代号 + 班级代号 + 学生学号 + 请假原因 + 开始时间 + 结束时间 + 请假天数 + 申请时间 + 班主任审批状态 + 班主任审批时间 + 院系领导审批状态 + 院系领导代号 + 院系领导审批时间。

逻辑结构设计把数据字典落成了十二张具体的表。这里挑几张关键表看字段设计:

表名主键关键外键备注
studentstu_nostu_class, stu_major, stu_faculty学生基本信息
qingjiaidclass_id, stu_no, class_tea_id, coll_leader_id请假审批全链路
kaoqin_recordkaoqin_idstu_number, teacher_no, course_no出勤记录
classesclass_noclasstea_no班级与班主任绑定
coursecourse_no无课程基础信息

请假表的设计是整份课设里最完整的:它把两级审批的状态和时间都放在同一张表里,班主任审批状态和院系领导审批状态用 0/1/2 表示等待、同意、不同意。这样做的好处是查一条请假记录就能看到完整审批链,不需要再关联审批历史表。代价是如果以后要加第三级审批,就得改表结构。课程设计阶段这样设计没问题,二次开发时如果审批层级要扩展,建议拆出独立的审批流水表。

3. 建库实操:表空间、十二张表与约束的完整落地

3.1 表空间创建与存储参数

建表之前先建表空间,这是 Oracle 里比较工程化的做法。课程设计里用的是字典管理表空间,目的是方便用 SQL 字典跟踪磁盘使用情况。

-- 创建字典管理表空间,指定数据文件路径和初始大小 create tablespace linpeng_data datafile '/u01/oracle/oradata/tab01.dbf' size 100M default storage( initial 512K -- 初始区大小 next 128K -- 下一个区大小 minextents 2 -- 最小区数 maxextents 999 -- 最大区数 pctincrease 0 -- 区增长百分比为0,避免空间浪费 ) online;

这段命令里几个参数值得说清楚。initial 512K是第一个区的大小,next 128K是后续区的大小,pctincrease 0表示每个后续区大小不递增,保持固定。minextents 2保证表空间创建时至少分配两个区。数据文件路径/u01/oracle/oradata/tab01.dbf是常见做法,实际环境里要换成自己机器上的路径。如果是在 Windows 上跑,路径要改成类似D:\oracle\oradata\tab01.dbf。

提示:如果只是本地跑课程设计,表空间不是必须的,直接用默认表空间也能建表。但加上表空间能体现对 Oracle 存储结构的理解,答辩时是个加分项。

3.2 核心表建表语句与约束设计

十二张表里,学生表、请假表、考勤记录表是最核心的三张。先看学生表:

-- 学生表:学号主键,性别用 check 约束,班级/专业/学院用外键 create table student( stu_no char(10) not null, stu_name varchar(30) not null, stu_sex char(2) check (stu_sex='男' or stu_sex='女'), stu_class char(5) foreign key references classes(class_no), stu_major number foreign key references major(major_id), stu_faculty number foreign key references faculty(faculty_id), constraint pk_student primary key(stu_no) ) tablespace linpeng_data;

这里有几个细节。stu_sex用check约束限定只能填“男”或“女”,这是数据库端的数据校验,比应用层校验更可靠。stu_class、stu_major、stu_faculty都是外键,分别指向班级表、专业表、院系表,保证学生所属的班级、专业、院系在基础表里一定存在。constraint pk_student primary key(stu_no)显式命名主键约束,方便后续维护时按名字引用。

再看请假表,这是字段最多的一张:

-- 请假表:记录两级审批状态和时间,外键关联班级、学生、班主任、院系领导 create table qingjia( id number primary key, class_id char(10) foreign key references classes(class_no), stu_no char(10) foreign key references student(stu_no), leave_reason varchar2(200) not null, start_time datetime not null, end_time datetime not null, day_number number not null, qingjia_time datetime not null, class_tea_id char(5) foreign key references classteacher(classtea_no), class_tea_sp_status char(10), class_tea_sp_time datetime, coll_leader_sp_status char(10), coll_leader_id char(5) foreign key references collegeleader(collegeleader_no), coll_leader_sp_time datetime ) tablespace linpeng_data;

请假表的设计逻辑是:一条请假记录从提交到最终审批完成,所有状态都在这张表里。class_tea_sp_status和coll_leader_sp_status分别存班主任和院系领导的审批状态,0 表示等待审批,1 表示同意,2 表示不同意。class_tea_sp_time和coll_leader_sp_time记录审批时间。day_number存请假天数,系统根据这个字段判断是否需要院系领导审批——超过三天才流转到院系领导。

考勤记录表的设计相对简单,但外键关系很关键:

-- 考勤记录表:关联学生、教师、课程,stu_status 存出勤状态 create table kaoqin_record( kaoqin_id char(13) primary key not null, sk_time datetime not null, stu_number char(10) foreign key references student(stu_no), stu_status char(10) not null, teacher_no char(10) foreign key references teacher(tea_no), course_no char(13) foreign key references course(course_no) ) tablespace linpeng_data;

stu_status存的是学生上课考勤状态,比如“出勤”“缺勤”“请假”。任课老师录入时,系统会根据stu_number和course_no去请假表里查该学生该课程当天是否有已批准的请假记录,如果有就自动填“请假”,否则由老师手动标记。

3.3 存储过程、视图与触发器的工程化用法

课程设计里最体现 Oracle 工程化能力的是三个数据库对象:存储过程、视图、触发器。

存储过程用于统计某学生某门课程的缺勤次数:

-- 统计指定学生指定课程的缺勤次数,结果通过 out 参数返回 create or replace procedure getMessage( stu_no in varchar2, course_no in varchar2, total_times out number ) as absence_times number; begin select count(*) into absence_times from kaoqin_record where stu_number = stu_no and course_no = course_no; total_times := absence_times; end;

这个存储过程接收学生学号和课程号,从考勤记录表里统计该学生该课程的记录数,通过out参数返回。调用时用call getMessage('学号', '课程号', :结果变量)。参数说明:stu_no和course_no是输入参数,total_times是输出参数。实际使用时,缺勤次数应该只统计stu_status为“缺勤”的记录,这里课程设计里简化成了统计所有记录,二次开发时记得加上状态过滤。

视图用于做院系级别的数据隔离:

-- 创建软件学院领导专用视图,只显示本院系学生的考勤记录 create view rjxy as select kaoqin_record.kaoqin_id, kaoqin_record.sk_time, kaoqin_record.stu_number, kaoqin_record.stu_status, kaoqin_record.teacher_no, kaoqin_record.course_no from kaoqin_record, student where student.stu_no = kaoqin_record.stu_number and student.stu_faculty = 5;

这个视图把考勤记录和学生表关联,过滤条件student.stu_faculty = 5限定只显示院系编号为 5 的学生记录。院系领导查询时直接查这个视图,就看不到其他院系的数据。这是数据库端做权限隔离的常见做法,比在应用层过滤更安全。

触发器用于缺勤次数超限时给出提示:

-- 插入考勤记录后触发,如果某学生某课程缺勤达到3次,输出提示 create or replace trigger alertMessage after insert on kaoqin_record for each row declare current_times number; begin select count(*) into current_times from kaoqin_record where stu_number = :new.stu_number and course_no = :new.course_no; if (current_times >= 3) then dbms_output.put_line('学号为:' || :new.stu_number || '的学生该门课程被取消考试资格!'); end if; end;

触发器在每次向考勤记录表插入数据后执行,统计该学生该课程的记录数,达到 3 次就输出提示。:new.stu_number和:new.course_no是刚插入的那条记录里的字段值。这里同样简化了,统计的是所有记录而不是缺勤记录,二次开发时要加上stu_status = '缺勤'的条件。

4. 避坑与排查:建表和跑存储过程时容易翻车的几个点

4.1 外键依赖顺序导致建表失败

现象:执行建表语句时报ORA-00942: table or view does not exist,提示引用的表不存在。

原因:建表顺序不对。学生表引用了班级表、专业表、院系表,如果先建学生表,这些被引用的表还不存在,外键约束就会失败。

解决:按依赖顺序建表。先建无外键的基础表——faculty、major、course、classteacher、collegeleader、schoolleader、admin,再建 classes(引用 classteacher),然后建 student(引用 classes、major、faculty),最后建 qingjia 和 kaoqin_record(引用 student、teacher、course)。如果已经建错了,用drop table 表名 cascade constraints删掉重建。

4.2 表空间路径不存在导致创建失败

现象:执行create tablespace时报ORA-01119: error in creating database file。

原因:datafile指定的路径/u01/oracle/oradata/在本地机器上不存在,或者 Oracle 进程没有该目录的写权限。

解决:先确认 Oracle 的数据文件目录在哪里,用show parameter db_create_file_dest查看默认路径,或者直接改成自己环境里存在的目录。Windows 环境下路径要写成D:\oracle\oradata\tab01.dbf这种格式。如果只是本地练习,可以跳过表空间,建表时不加tablespace子句,用默认表空间。

4.3 存储过程编译通过但调用报错

现象:create or replace procedure执行成功,但call getMessage(...)时报ORA-06550或ORA-00904。

原因:常见的是参数类型不匹配。存储过程定义时stu_no是varchar2,调用时传了数字字面量,Oracle 隐式转换失败。或者out参数在调用时没有用绑定变量接收。

解决:调用时确保参数类型一致,字符串加单引号。在 SQL*Plus 里调用带out参数的过程,需要先variable 结果变量 number声明绑定变量,再execute getMessage('学号', '课程号', :结果变量),最后print 结果变量查看结果。

4.4 触发器里的 dbms_output 看不到输出

现象:触发器创建成功,插入数据后没有任何提示信息。

原因:dbms_output.put_line的输出需要先执行set serveroutput on才能显示。另外,如果插入操作是在应用层执行的,输出会留在数据库端,应用层看不到。

解决:在 SQL*Plus 里先执行set serveroutput on,再执行插入语句。如果是在 Java 或 Python 里调用,触发器输出不会传到应用层,需要改成写日志表的方式——建一张alert_log表,触发器里改成insert into alert_log,应用层再查这张表。

4.5 视图查询结果为空但基表有数据

现象:创建了院系视图rjxy,查询时返回空结果,但kaoqin_record和student表里明明有数据。

原因:视图的过滤条件student.stu_faculty = 5写死了院系编号,如果实际数据里学生的stu_faculty不是 5,或者student.stu_no和kaoqin_record.stu_number关联不上(比如学号格式不一致),就会返回空。

解决:先单独查select * from student where stu_faculty = 5确认有数据,再查select * from kaoqin_record where stu_number in (select stu_no from student where stu_faculty = 5)确认关联能匹配上。如果学号字段一个是char(10)一个是varchar2(20),可能存在空格填充问题,用trim()处理后再关联。

5. 二次开发:从课程设计到可运行系统的改造思路

5.1 补全缺失的查询和更新逻辑

这份课程设计把建表、约束、存储过程、视图、触发器都写了,但缺少日常业务里最常用的查询和更新语句。二次开发时,第一件事是把这些补上。比如学生查看自己某学期某课程的出勤详情:

-- 查询指定学生指定课程的出勤记录,按时间倒序 select sk_time, stu_status, teacher_no from kaoqin_record where stu_number = '目标学号' and course_no = '目标课程号' order by sk_time desc;

班主任查看本班待审批的请假:

-- 查询本班所有等待班主任审批的请假记录 select q.id, s.stu_name, q.leave_reason, q.start_time, q.end_time, q.day_number from qingjia q, student s where q.stu_no = s.stu_no and s.stu_class = '目标班级号' and q.class_tea_sp_status = '0' order by q.qingjia_time asc;

院系领导查看超过三天且班主任已同意的请假:

-- 查询需要院系领导审批的请假:天数超过3天且班主任已同意 select q.id, s.stu_name, q.leave_reason, q.day_number from qingjia q, student s where q.stu_no = s.stu_no and s.stu_faculty = 目标院系编号 and q.day_number > 3 and q.class_tea_sp_status = '1' and q.coll_leader_sp_status = '0';

这些查询语句是系统跑起来的基础。课程设计里没写,但实际开发时每个角色至少需要三到五条这样的查询。

5.2 把存储过程改造成更实用的版本

原来的getMessage存储过程统计的是所有考勤记录数,没有区分出勤状态。二次开发时改成只统计缺勤:

-- 改造版:只统计缺勤次数,排除请假和出勤 create or replace procedure getAbsenceTimes( p_stu_no in varchar2, p_course_no in varchar2, p_absence_times out number ) as begin select count(*) into p_absence_times from kaoqin_record where stu_number = p_stu_no and course_no = p_course_no and stu_status = '缺勤'; end;

参数命名加上p_前缀,避免和列名冲突。过滤条件加上stu_status = '缺勤',这样统计出来的才是真正的缺勤次数。调用方式和原来一样,但结果更准确。

5.3 用日志表替代 dbms_output 做超限提醒

触发器里的dbms_output.put_line在实际系统里看不到,改成写日志表:

-- 先建日志表 create table alert_log( log_id number primary key, stu_no char(10), course_no char(13), alert_time datetime, alert_msg varchar2(200) ); -- 改造触发器:插入日志表而不是输出 create or replace trigger alertMessage after insert on kaoqin_record for each row declare current_times number; begin select count(*) into current_times from kaoqin_record where stu_number = :new.stu_number and course_no = :new.course_no and stu_status = '缺勤'; if (current_times >= 3) then insert into alert_log(log_id, stu_no, course_no, alert_time, alert_msg) values(seq_alert_log.nextval, :new.stu_number, :new.course_no, sysdate, '该学生该课程缺勤已达3次,取消考试资格'); end if; end;

这样应用层只需要定时查alert_log表就能拿到所有超限提醒,不依赖数据库端的输出。seq_alert_log需要提前创建序列:create sequence seq_alert_log start with 1 increment by 1;。

5.4 验证改造是否成功的检查清单

改完之后怎么确认没问题?我一般会走一遍这个流程:先确认所有表建成功,用select table_name from user_tables;查一遍;再确认约束生效,试着插入一条性别为“未知”的学生记录,应该报 check 约束错误;然后调用改造后的存储过程,传一个已知有缺勤记录的学生学号和课程号,看返回的缺勤次数对不对;接着插入一条缺勤记录,查alert_log表看有没有新增日志;最后用不同院系的账号查视图,确认只能看到自己院系的数据。

从那以后我每次改完数据库对象,都强制走一遍这个检查清单,尤其是外键和触发器相关的改动,不跑一遍心里不踏实。希望这份拆解能帮你把这份课程设计真正跑起来,而不是让它躺在硬盘里吃灰。

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

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

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

立即咨询