资讯详情

资讯详情

Oracle学生考勤系统数据库设计实战:从表空间到触发器

简介这份Oracle数据库课程设计资料面向学习数据库管理与开发的学生及IT从业者以“学生考勤系统”为完整案例帮助读者掌握从需求分析到数据库落地的全流程设计方法。内容涵盖系统背景分析、多角色用户需求学生、任课老师、班主任、院系领导、学校领导、系统管理员、功能模块划分请假、考勤、后台管理、E-R模型、数据字典、表逻辑结构以及表空间与建表脚本等环节并延伸至SQL查询、存储过程、触发器、性能优化与备份恢复等进阶主题。资源包共1个doc文件约227KB为辽宁工程技术大学软件学院的课程设计报告目录结构完整、章节清晰可直接作为课程设计参考模板或自学范例。目前已有965人学习下载适合需要完成数据库课程设计、理解Oracle建模与实现思路的读者借鉴使用。1. 从一份 2009 年的 Oracle 课程设计说起学生考勤系统到底能跑出什么翻到这份 Oracle 数据库课程设计的时候我第一反应是——这玩意儿太适合拿来练手了。它不是什么花哨的微服务项目就是一个老老实实的学生考勤系统用 Oracle 做后端把请假审批、出勤记录、多角色权限管理全塞进了一个数据库里。你如果正在找一份能直接跑、能改、能拿去交课程设计或者当 Oracle 练手素材的东西这份资源基本能满足。它覆盖了从需求分析、E-R 模型、数据字典到表空间创建、建表、存储过程、视图、触发器的完整链路六大类用户角色学生、任课老师、班主任、院系领导、学校领导、系统管理员各有各的操作路径。说白了这就是一个用 Oracle 把高校考勤业务逻辑从头到尾实现一遍的工程实践适合学数据库的学生、刚接触 Oracle 的开发者以及需要一份完整数据库设计参考的人。2. 需求到模型六大角色怎么映射成十二张表2.1 用户角色与功能模块的对应关系这个系统的业务逻辑其实不复杂但角色多权限层次分明。学生要在线请假、查自己的出勤记录任课老师要录入和查看所教班级的出勤班主任要审批本班请假、看本班出勤统计院系领导要审批超过三天的请假、查看本院系出勤学校领导看全校数据系统管理员维护所有基础数据。六个角色对应三个功能模块请假系统、考勤系统、后台管理。我一般拿到这种需求第一步不是急着建表而是先把角色和操作的对应关系画清楚。这份课程设计里用 E-R 模型做了这件事实体包括教师、班级、学生、学院领导、学院、专业、课程、假条、考勤关系有开设、授课、聘请、班主任、管理、请假、属于等。E-R 图里标注了 1:1、1:n、m:n 的基数这是后面建表时确定外键方向的关键依据。2.2 数据字典字段定义的规范化起点数据字典这部分是很多课程设计里容易被糊弄过去的但这份资源写得比较细。它把每个实体的属性用“名字 描述 定义”的格式列出来比如请假条信息定义为请假代号 班级代号 学生学号 请假原因 开始时间 结束时间 请假天数 申请请假时间 班主任审批状态 班主任审批时间 院系领导审批状态 院系领导代号 院系领导审批时间。这种写法看起来啰嗦但好处是后面建表的时候字段一个都不会漏。我见过太多人跳过数据字典直接建表结果做到一半发现少了个审批时间字段回头改表结构外键约束全得重来。所以这一步别省。2.3 逻辑结构设计十二张表的字段与约束从 E-R 模型到逻辑结构核心工作就是把实体转成表、把关系转成外键。这份设计里一共十二张表我挑几个关键的说一下字段设计的思路。系统管理员表 admin 用 admin_no 做主键admin_sex 加了 check 约束限定只能填“男”或“女”。学生表 student 的主键是 stu_nostu_class、stu_major、stu_faculty 分别外键引用班级表、专业表、院系表。这里有个细节值得注意学生表里同时存了班级、专业、院系三个外键而不是通过班级表间接关联到专业和院系。这样做查询方便但数据一致性维护成本高——如果学生转专业三个字段都得改。常见做法是只保留班级外键专业和院系通过班级表往上查但这份设计选择了冗余换查询效率在课程设计场景下也说得过去。请假信息表 qingjia 是字段最多的包含了完整的审批链路班主任审批状态、班主任审批时间、院系领导审批状态、院系领导代号、院系领导审批时间。审批状态用 0/1/2 表示等待审批、同意、不同意。这种用数字编码状态的做法在数据库设计里很常见比存中文字符串省空间但记得在应用层做好映射。出勤记录表 kaoqin_record 的主键是 kaoqin_id同时外键关联学生、教师、课程三张表。这意味着一条出勤记录必须同时确定“谁、哪门课、哪个老师记录的”粒度很清晰。3. 表空间与建表实战从 CREATE TABLESPACE 到十二张表落地3.1 表空间设计为什么先建表空间再建表这份课程设计里专门用了一节讲表空间创建命令是这样的create tablespace linpeng_data datafile /u01/oracle/oradata/tab01.dbf size 100M default storage( initial 512K next 128K minextents 2 maxextents 999 pctincrease 0 ) online;逻辑说明datafile指定物理文件路径size 100M是初始大小。default storage子句定义了段segment的默认存储参数——initial 512K是初始区大小next 128K是后续扩展区大小minextents 2表示每个段至少分配两个区maxextents 999限制最大区数量pctincrease 0表示区大小不自动递增。online让表空间立即可用。参数怎么改如果你只是本地练习datafile路径改成你 Oracle 安装目录下的实际路径就行。size可以调小到 50M课程设计的数据量用不了 100M。maxextents在现代 Oracle 里其实已经不太需要手动设了但课程设计里写上显得规范。注意建表空间之前确认你用的用户有CREATE TABLESPACE权限普通用户默认没有得用 DBA 账号授权或者直接用 DBA 账号操作。3.2 建表语句逐段拆解约束、外键与表空间归属建表部分一共十二条CREATE TABLE我挑几条有代表性的讲。先看系统管理员表create table admin( admin_no char(5) not null, admin_name char(10) not null, admin_sex char(2) check (admin_sex男 or admin_sex女), admin_title char(20) not null, admin_password varchar(20) not null, constraint pk_admin primary key (admin_no) ) tablespace linpeng_data;逻辑说明admin_no用char(5)定长因为管理员编号格式固定。admin_sex用check约束限定取值范围这是数据库层面保证数据质量的手段。constraint pk_admin primary key显式命名了主键约束方便后续维护时引用。最后的tablespace linpeng_data把表放到刚才建的表空间里。再看学生表的外键设计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_class、stu_major、stu_faculty三个字段都是外键分别引用班级表、专业表、院系表。注意建表顺序——必须先建classes、major、faculty再建student否则外键引用会报错。这是新手最容易翻车的地方建表脚本的执行顺序必须按依赖关系排好。请假信息表的建表语句里有个细节值得注意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;审批状态和审批时间字段允许为空因为请假刚提交时还没有审批记录。leave_reason用varchar2(200)给的理由留了足够空间。day_number是请假天数后面院系领导审批时会根据这个字段判断是否需要自己处理超过三天。3.3 存储过程、视图与触发器把业务逻辑下沉到数据库端这份课程设计的一个亮点是把一些关键业务逻辑用存储过程、视图和触发器封装在数据库端。先看统计学生某门课出勤情况的存储过程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;逻辑说明输入参数是学号和课程号输出参数是该学生在这门课上的缺勤次数。select count(*) into把查询结果赋给变量最后通过out参数返回。调用方式是在 SQL*Plus 里声明变量然后exec getMessage(学号, 课程号, :变量名)。参数说明stu_no和course_no都是in参数total_times是out参数。注意原文里写的是total_timesabsence_times这在 PL/SQL 里应该是:赋值直接写会报错实际运行时需要改成total_times : absence_times;。再看视图作用是让不同院系的领导只能看到自己学院的数据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;这里假设软件学院的 ID 是 5视图把出勤记录和学生表关联过滤出该学院的学生数据。院系领导查询时直接查这个视图就行不用关心底层表结构。如果要给其他学院建视图把stu_faculty 5改成对应的院系 ID 即可。触发器的作用是当学生某门课缺勤超过三次时给出提示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;逻辑说明这是一个行级触发器在kaoqin_record表每次插入新记录后触发。:new.stu_number和:new.course_no引用刚插入的那行数据。触发器统计该学生该课程的总缺勤次数达到三次就输出提示。注意dbms_output.put_line的输出需要在 SQL*Plus 里先执行set serveroutput on才能看到。另外这个触发器只做了提示没有实际修改数据或阻止插入属于“提醒型”触发器。如果要真正限制考试资格得配合应用层逻辑或者改成before insert触发器加raise_application_error。4. 避坑与排查建表和外键约束里最容易翻车的几个点4.1 建表顺序不对导致外键创建失败现象执行建表脚本时报ORA-00942: table or view does not exist提示引用的表不存在。原因student表的外键引用了classes、major、faculty如果先建student再建classesOracle 找不到被引用的表。解决按依赖关系排序建表。先建无外键的表faculty、major、course、classteacher、collegeleader、schoolleader、admin再建依赖它们的表classes、teacher、student最后建kaoqin_record和qingjia。我一般会在脚本开头加注释标明执行顺序。4.2 表空间路径不存在导致建表空间失败现象执行CREATE TABLESPACE时报ORA-01119: error in creating database file。原因datafile指定的路径/u01/oracle/oradata/tab01.dbf在你的机器上不存在或者 Oracle 进程没有该目录的写权限。解决先确认 Oracle 的数据文件目录用SELECT name FROM v$datafile;查看现有数据文件路径照着改。Windows 下路径格式是D:\oracle\oradata\tab01.dbf注意用反斜杠或双斜杠。4.3 存储过程编译报错但看不到具体错误现象CREATE OR REPLACE PROCEDURE执行后提示“已创建过程但存在编译错误”。原因PL/SQL 编译错误不会直接显示需要额外查询。解决执行SHOW ERRORS PROCEDURE getMessage;或者查SELECT * FROM user_errors WHERE name GETMESSAGE;。常见错误包括赋值符号写成而不是:、变量未声明、select into返回多行等。原文里total_timesabsence_times就是典型的赋值符号错误。4.4 触发器里 dbms_output 看不到输出现象触发器创建成功插入数据也成功但看不到提示信息。原因dbms_output.put_line的输出默认不显示需要开启 serveroutput。解决在 SQL*Plus 里先执行SET SERVEROUTPUT ON;再执行插入操作。如果用的是其他客户端工具找对应的“启用 DBMS 输出”选项。4.5 外键约束导致插入数据顺序受限现象往student表插入数据时报ORA-02291: integrity constraint violated - parent key not found。原因stu_class引用了classes表的class_no但classes表里还没有对应的班级记录。解决先往被引用的表classes、major、faculty插入基础数据再往student表插。删除数据时顺序反过来先删子表再删父表或者用ON DELETE CASCADE但这份设计里没加级联删除所以得手动处理。5. 二次开发与改造从课程设计到能用的考勤系统还差什么5.1 把审批状态从数字改成可读的枚举原文里审批状态用 0/1/2 表示查询的时候不直观。我一般会建一个状态码表create table approval_status ( status_code number primary key, status_name varchar2(20) not null ); insert into approval_status values (0, 等待审批); insert into approval_status values (1, 同意请假); insert into approval_status values (2, 不同意请假);然后查询请假信息时关联这张表把状态码翻译成中文。这样前端展示和报表输出都省事。5.2 给请假表加一个自动计算天数的触发器原文里day_number是手动填的容易填错。可以加一个before insert or update触发器根据start_time和end_time自动算create or replace trigger calc_leave_days before insert or update on qingjia for each row begin :new.day_number : trunc(:new.end_time) - trunc(:new.start_time) 1; end;这样插入请假记录时只需要填开始和结束时间天数自动算出来。注意trunc是把时间部分截掉只留日期避免同一天请假算出 0 天。5.3 用存储过程封装完整的请假审批流程原文的审批逻辑散落在应用层可以封装成一个存储过程create or replace procedure approve_leave( p_qingjia_id in number, p_approver_type in varchar2, -- CLASS_TEACHER 或 COLLEGE_LEADER p_approver_id in varchar2, p_approved in number -- 1 同意2 不同意 ) as v_days number; begin select day_number into v_days from qingjia where id p_qingjia_id; if p_approver_type CLASS_TEACHER then update qingjia set class_tea_sp_status p_approved, class_tea_sp_time sysdate, class_tea_id p_approver_id where id p_qingjia_id; elsif p_approver_type COLLEGE_LEADER then if v_days 3 then update qingjia set coll_leader_sp_status p_approved, coll_leader_sp_time sysdate, coll_leader_id p_approver_id where id p_qingjia_id; else raise_application_error(-20001, 请假天数不超过三天无需院系领导审批); end if; end if; commit; end;这个存储过程把审批逻辑收拢到数据库端应用层只需要传参数调用。好处是审批规则变了只改存储过程不用重新部署应用。注意raise_application_error用来抛出自定义错误错误码 -20001 是用户自定义范围的起始值。5.4 验证改造效果的方法改完之后怎么确认没问题我一般分三步走先用SELECT查一遍基础数据确认院系、专业、班级、学生、课程都有记录然后模拟一次完整请假流程——插入请假记录、调用审批存储过程、查询审批状态和天数最后往kaoqin_record表插入几条缺勤记录看触发器有没有输出提示。每一步都手动执行 SQL别急着写应用层代码数据库端逻辑跑通了再往上搭。从那以后我每次拿到这种课程设计类的数据库项目都强制自己先把建表脚本按依赖顺序排一遍再逐条执行确认没有外键报错最后才去碰存储过程和触发器。这个习惯帮我省了不少回头改表结构的时间。希望帮到你。本文还有配套的精品资源点击获取
觉得有用,分享给同行:

为您的企业打造数字门面

稳重轻奢商务风格,端正雅致视觉,长效耐看不易过时。

立即咨询 →