Oracle实验二 编写ORACLE触发器与过程

版权声明:@YDDUONG https://blog.csdn.net/y_dd6011/article/details/86344734

一、实验内容

    1.设计与建立上课考勤表t_attend_j432,能登记每个学生的考勤记录包括正常、迟到、旷课、请假。能统计以专业为单位的出勤类别并进行打分评价排序,如迟到、旷课、请假分别扣2,5,1分。可以考虑给一初始的分值,以免负值。

    2.为t_major_j432表与t_stud_432表增加sum_evaluation 数值字段,以记录根据考勤表t_attend_j432(Attendance)中出勤类别打分汇总的值(这两张表参考实验一)。

    3.建立个人考勤汇总表t_stud_atte_j432与专业考勤表t_major_atte_j432,表示每个学生或每个专业在某时间周期(起始日期,终止日期)正常、迟到、旷课、请假次数及考勤分值。

    4.根据实验一t_major_j432表中的值与t_stud_j432中的值,为考勤表t_attend_j432输入足够的样本值,要求每个专业都要有学生,有部分学生至少要有一周的每天5个单元(12,34,56,78,90,没有课的单元可以没有考勤记录)的考勤完整记录,其中正常、迟到、旷课、请假 可以用数字或字母符号表示。

    5.建立触发器,当对考勤表t_attend_j432表进行相应插入、删除、修改时,对t_stud_432表的sum_evaluation 数值进行相应的数据更新。

    6.建立过程,生成某专业某时段(起、止日期)的考勤汇总表t_major_atte_j432中各字段值,并汇总相应专业,将考勤分值的汇总结果写入到t_major_j432表中的sum_evaluation中。

二、实验源程序

conn c##u_j432/p123789
--1.为学生表和专业表各添加一列:考勤分数
desc t_stud_j432;
desc t_major_j432;
alter table t_stud_j432 add sum_evaluation number(3) default 100;
alter table t_major_j432 add sum_evaluation number(3) default 500;
desc t_stud_j432;
desc t_major_j432;

--2.建立考勤表
--正常:A
--迟到:B
--旷课:C
--请假:D
--没课:E
drop table t_attend_j432;
create table t_attend_j432(
	nowdate date not null,
	sno varchar(10) not null,
	name varchar(16) not null,
	class12 varchar(4) not null,
	class34 varchar(4) not null,
	class56 varchar(4) not null,
	class78 varchar(4) not null,
	class90 varchar(4) not null,
	constraint pk_attend_nowdate_sno primary key(nowdate,sno),
	constraint ck_attend_class12 check(class12 in('A','B','C','D','E')),
	constraint ck_attend_class34 check(class34 in('A','B','C','D','E')),
	constraint ck_attend_class56 check(class56 in('A','B','C','D','E')),
	constraint ck_attend_class78 check(class78 in('A','B','C','D','E')),
	constraint ck_attend_class90 check(class90 in('A','B','C','D','E')),
	constraint ck_attend_sno foreign key(sno) references t_stud_j432(sno));

--2.插入一周数据:2018.11.13至2018.11.19
insert into t_attend_j432 values(to_date('20181113','yyyymmdd'),'0921160114','李浩汉','A','B','C','A','E');
insert into t_attend_j432 values(to_date('20181113','yyyymmdd'),'0921160115','李文博','A','E','C','E','E');
insert into t_attend_j432 values(to_date('20181113','yyyymmdd'),'0921160117','徐聪','A','B','E','A','D');
insert into t_attend_j432 values(to_date('20181113','yyyymmdd'),'0921160120','周文轩','E','A','E','E','D');
--自己可添加数据

--3.显示考勤表
set linesize 150;
set pagesize 100;
col name format a7;
col sno format a11;
col class12 format a7;
col class34 format a7;
col class65 format a7;
col class78 format a7;
col class90 format a7;
alter session set nls_date_format = 'yyyy-mm-dd';
select * from t_attend_j432;

--4.建立学生考勤表
drop table t_stud_atte_j432;
create table t_stud_atte_j432(
	startdate date default to_date('21000101','yyyyddmm'),
	stopdate date default to_date('19000101','yyyyddmm'),
	sno varchar2(10),
	sname varchar2(32),
	class_a number(3) default 0,
	class_b number(3) default 0,
	class_c number(3) default 0,
	class_d number(3) default 0,
	result number(3) default 100,
	constraint pk_stud_atte_sno primary key(sno),
	constraint fk_stud_atte_sno foreign key(sno) references t_stud_j432(sno));

--5.将学生表的所有学生插入学生考勤表
insert into t_stud_atte_j432(sno,sname) select t_stud_j432.sno,t_stud_j432.sname from t_stud_j432;

--6.显示学生考勤表
col sname format a7;
alter session set nls_date_format = 'yyyy-mm-dd';
select * from t_stud_atte_j432;

--7.建立专业考勤表
drop table t_major_atte_j432;
create table t_major_atte_j432(
	startdate date default to_date('20181001','yyyyddmm'),
	stopdate date default to_date('20181001','yyyyddmm'),
	mno varchar2(2),
	mname varchar2(32),
	class_a number(3) default 0,
	class_b number(3) default 0,
	class_c number(3) default 0,
	class_d number(3) default 0,
	result number(3) default 500,
	constraint pk_major_atte_sno primary key(mno),
	constraint fk_major_atte_sno foreign key(mno) references t_major_j432(mno));

--8.将专业表的所有专业插入专业考勤表
insert into t_major_atte_j432(mno,mname) select t_major_j432.mno,t_major_j432.mname from t_major_j432;

--9.显示专业考勤表
col mname format a20;
alter session set nls_date_format = 'yyyy-mm-dd';
select * from t_major_atte_j432;

--10.建立过程:汇总学生考勤数据,并将成绩更新到学生表中
create or replace procedure p_stud_atte_j432
as
cursor stud_atte_line is select * from t_attend_j432;
cur_atte t_attend_j432%rowtype;
class_sa number(3);
class_sb number(3);
class_sc number(3);
class_sd number(3);
class_res number(3);

time_min date;
time_max date;
begin
delete from t_stud_atte_j432;
insert into t_stud_atte_j432(sno,sname) select t_stud_j432.sno,t_stud_j432.sname from t_stud_j432;
for cur_atte in stud_atte_line loop

	select startdate into time_min from t_stud_atte_j432 where t_stud_atte_j432.sno=cur_atte.sno;
	select stopdate into time_max from t_stud_atte_j432 where t_stud_atte_j432.sno=cur_atte.sno;
	select class_a into class_sa from t_stud_atte_j432 where t_stud_atte_j432.sno=cur_atte.sno;
	select class_b into class_sb from t_stud_atte_j432 where t_stud_atte_j432.sno=cur_atte.sno;
	select class_c into class_sc from t_stud_atte_j432 where t_stud_atte_j432.sno=cur_atte.sno;
	select class_d into class_sd from t_stud_atte_j432 where t_stud_atte_j432.sno=cur_atte.sno;
	
	if(time_min>cur_atte.nowdate)then
		time_min:=cur_atte.nowdate;
	end if;
	if(time_max<cur_atte.nowdate)then
		time_max:=cur_atte.nowdate;
	end if;

	if(cur_atte.class12='A')then
		class_sa:=class_sa+1;
	elsif(cur_atte.class12='B')then
		class_sb:=class_sb+1;
	elsif(cur_atte.class12='C')then
		class_sc:=class_sc+1;
	elsif(cur_atte.class12='D')then
		class_sd:=class_sd+1;
	end if;

	if(cur_atte.class34='A')then
		class_sa:=class_sa+1;
	elsif(cur_atte.class34='B')then
		class_sb:=class_sb+1;
	elsif(cur_atte.class34='C')then
		class_sc:=class_sc+1;
	elsif(cur_atte.class34='D')then
		class_sd:=class_sd+1;
	end if;

	if(cur_atte.class56='A')then
		class_sa:=class_sa+1;
	elsif(cur_atte.class56='B')then
		class_sb:=class_sb+1;
	elsif(cur_atte.class56='C')then
		class_sc:=class_sc+1;
	elsif(cur_atte.class56='D')then
		class_sd:=class_sd+1;
	end if;

	if(cur_atte.class78='A')then
		class_sa:=class_sa+1;
	elsif(cur_atte.class78='B')then
		class_sb:=class_sb+1;
	elsif(cur_atte.class78='C')then
		class_sc:=class_sc+1;
	elsif(cur_atte.class78='D')then
		class_sd:=class_sd+1;
	end if;

	if(cur_atte.class90='A')then
		class_sa:=class_sa+1;
	elsif(cur_atte.class90='B')then
		class_sb:=class_sb+1;
	elsif(cur_atte.class90='C')then
		class_sc:=class_sc+1;
	elsif(cur_atte.class90='D')then
		class_sd:=class_sd+1;
	end if;

	class_res:=100-class_sb*2-class_sc*5-class_sd;
	
	update t_stud_atte_j432 set t_stud_atte_j432.startdate=time_min where t_stud_atte_j432.sno=cur_atte.sno;
	update t_stud_atte_j432 set t_stud_atte_j432.stopdate=time_max where t_stud_atte_j432.sno=cur_atte.sno;
	update t_stud_atte_j432 set t_stud_atte_j432.class_a=class_sa where t_stud_atte_j432.sno=cur_atte.sno;
	update t_stud_atte_j432 set t_stud_atte_j432.class_b=class_sb where t_stud_atte_j432.sno=cur_atte.sno;
	update t_stud_atte_j432 set t_stud_atte_j432.class_c=class_sc where t_stud_atte_j432.sno=cur_atte.sno;
	update t_stud_atte_j432 set t_stud_atte_j432.class_d=class_sd where t_stud_atte_j432.sno=cur_atte.sno;
	update t_stud_atte_j432 set t_stud_atte_j432.result=class_res where t_stud_atte_j432.sno=cur_atte.sno;
	update t_stud_j432 set t_stud_j432.sum_evaluation=class_res where t_stud_j432.sno=cur_atte.sno;
end loop;
end;
/
show error

--11.显示学生考勤表
exec p_stud_atte_j432;
col sname format a7;
alter session set nls_date_format = 'yyyy-mm-dd';
select * from t_stud_atte_j432;

--12.查看两名学生的考勤记录,查看数据汇总是否正确
select * from t_attend_j432 where name='冯玲';
select * from t_attend_j432 where name='吴月颖';

--13.建立过程:汇总专业考勤数据,并将成绩更新到专业表中
create or replace procedure p_major_atte_j432(start_mtime date,stop_mtime date)
as
cursor major_atte_line is select * from t_attend_j432 where t_attend_j432.nowdate>=start_mtime and t_attend_j432.nowdate<=stop_mtime;
cur_atte t_attend_j432%rowtype;
class_ma number(3);
class_mb number(3);
class_mc number(3);
class_md number(3);
class_res number(3);
begin
delete from t_major_atte_j432;
insert into t_major_atte_j432(mno,mname) select t_major_j432.mno,t_major_j432.mname from t_major_j432;

for cur_atte in major_atte_line loop

	select class_a into class_ma from t_major_atte_j432 where t_major_atte_j432.mno=substr(cur_atte.sno,3,2);
	select class_b into class_mb from t_major_atte_j432 where t_major_atte_j432.mno=substr(cur_atte.sno,3,2);
	select class_c into class_mc from t_major_atte_j432 where t_major_atte_j432.mno=substr(cur_atte.sno,3,2);
	select class_d into class_md from t_major_atte_j432 where t_major_atte_j432.mno=substr(cur_atte.sno,3,2);

	if(cur_atte.class12='A')then
		class_ma:=class_ma+1;
	elsif(cur_atte.class12='B')then
		class_mb:=class_mb+1;
	elsif(cur_atte.class12='C')then
		class_mc:=class_mc+1;
	elsif(cur_atte.class12='D')then
		class_md:=class_md+1;
	end if;

	if(cur_atte.class34='A')then
		class_ma:=class_ma+1;
	elsif(cur_atte.class34='B')then
		class_mb:=class_mb+1;
	elsif(cur_atte.class34='C')then
		class_mc:=class_mc+1;
	elsif(cur_atte.class34='D')then
		class_md:=class_md+1;
	end if;

	if(cur_atte.class56='A')then
		class_ma:=class_ma+1;
	elsif(cur_atte.class56='B')then
		class_mb:=class_mb+1;
	elsif(cur_atte.class56='C')then
		class_mc:=class_mc+1;
	elsif(cur_atte.class56='D')then
		class_md:=class_md+1;
	end if;

	if(cur_atte.class78='A')then
		class_ma:=class_ma+1;
	elsif(cur_atte.class78='B')then
		class_mb:=class_mb+1;
	elsif(cur_atte.class78='C')then
		class_mc:=class_mc+1;
	elsif(cur_atte.class78='D')then
		class_md:=class_md+1;
	end if;

	if(cur_atte.class90='A')then
		class_ma:=class_ma+1;
	elsif(cur_atte.class90='B')then
		class_mb:=class_mb+1;
	elsif(cur_atte.class90='C')then
		class_mc:=class_mc+1;
	elsif(cur_atte.class90='D')then
		class_md:=class_md+1;
	end if;

	class_res:=500-class_mb*2-class_mc*5-class_md;
	
	update t_major_atte_j432 set t_major_atte_j432.startdate=start_mtime where t_major_atte_j432.mno=substr(cur_atte.sno,3,2);
	update t_major_atte_j432 set t_major_atte_j432.stopdate=stop_mtime where t_major_atte_j432.mno=substr(cur_atte.sno,3,2);
	update t_major_atte_j432 set t_major_atte_j432.class_a=class_ma where t_major_atte_j432.mno=substr(cur_atte.sno,3,2);
	update t_major_atte_j432 set t_major_atte_j432.class_b=class_mb where t_major_atte_j432.mno=substr(cur_atte.sno,3,2);
	update t_major_atte_j432 set t_major_atte_j432.class_c=class_mc where t_major_atte_j432.mno=substr(cur_atte.sno,3,2);
	update t_major_atte_j432 set t_major_atte_j432.class_d=class_md where t_major_atte_j432.mno=substr(cur_atte.sno,3,2);
	update t_major_atte_j432 set t_major_atte_j432.result=class_res where t_major_atte_j432.mno=substr(cur_atte.sno,3,2);
	update t_major_j432 set t_major_j432.sum_evaluation=class_res where t_major_j432.mno=substr(cur_atte.sno,3,2);
end loop;
end;
/
show error

--14.显示专业考勤表
exec p_major_atte_j432('20181113','20181119');
col mname format a20;
alter session set nls_date_format = 'yyyy-mm-dd';
select * from t_major_atte_j432;

--15.建立触发器:当对考勤表进行相应插入、删除、修改时,对stud表的sum_evaluation数值进行相应的数据更新
create or replace trigger tg_attend_j432
after insert or update or delete on t_attend_j432
begin
p_stud_atte_j432;
end;
/

--16.测试触发器
column sno format a11;
column sname format a7;
column sex format a4;
column tel format a12;
column email format a32;
column birthday format a11;
column mno format a11;
column majorno format a3;
set linesize 150;
set pagesize 100;
alter session set nls_date_format = 'yyyy-mm-dd';
--插入测试
select * from t_stud_j432 where sname='郭泽华';
insert into t_attend_j432 values(to_date('20181120','yyyymmdd'),'0919160110','郭泽华','B','B','B','E','E');
select * from t_stud_j432 where sname='郭泽华';

--删除测试
select * from t_stud_j432 where sname='郭泽华';
delete from t_attend_j432 where name='郭泽华' and nowdate=to_date('20181120','yyyymmdd');
select * from t_stud_j432 where sname='郭泽华';

--更新测试
select * from t_attend_j432 where name='郭泽华';
select * from t_stud_j432 where sname='郭泽华';
update t_attend_j432 set class12='C' where name='郭泽华' and nowdate=to_date('20181119','yyyymmdd');
select * from t_attend_j432 where name='郭泽华';
select * from t_stud_j432 where sname='郭泽华';

三、实验分析及过程截图

1.实验思路:t_major_j432表与t_stud_432

    1)为学生t_stud_432和专业表t_major_j432分别添加一列result(用于记录每个学生和专业的考勤成绩)。

    2)建立考勤表t_attend_j432(记录方式正常:A;迟到:B;旷课:C;请假:D;没课:E),之后插入一周七天的数据。

    3)建立学生考勤表t_stud_atte_j432和专业考勤表t_major_atte_j432(同时导入学生和专业信息,学生和专业成绩初始值分别为100和500,其余值默认为0)。

    4)建立过程p_stud_atte_j432:汇总学生考勤数据,并将成绩更新到学生表中。

扫描二维码关注公众号,回复: 4880683 查看本文章

    5)建立过程p_major_atte_j432(start_mtime date,stop_mtime date):汇总专业考勤数据,并将成绩更新到专业表中。

    6)建立触发器tg_attend_j432:当对考勤表进行相应插入、删除、修改时,对t_stud_432表的result数值进行相应的数据更新。

2.学生考勤数据汇总过程p_stud_atte_j432分析(专业考勤数据汇总过程类似,不再分析)

create or replace procedure p_stud_atte_j432

as

cursor stud_atte_line is select * from t_attend_j432;--对考勤表建立游标

cur_atte t_attend_j432%rowtype;

class_sa number(3);--正常上课状态A的次数

class_sb number(3);--上课迟到状态B的次数

class_sc number(3);--上课缺勤状态C的次数

class_sd number(3);--上课请假状态D的次数

class_res number(3);--当前考勤成绩

time_min date;--最小日期

time_max date;--最大日期

Begin

--先删除学生考勤表的所有记录,然后插入所有学号和学生姓名,成绩默认为100,其他属性默认为0

delete from t_stud_atte_j432;

insert into t_stud_atte_j432(sno,sname) select t_stud_j432.sno,t_stud_j432.sname from t_stud_j432;

for cur_atte in stud_atte_line loop--开启游标循环

--获取学生考勤表的当前记录

select startdate into time_min from t_stud_atte_j432 where t_stud_atte_j432.sno=cur_atte.sno;

select stopdate into time_max from t_stud_atte_j432 where t_stud_atte_j432.sno=cur_atte.sno;

select class_a into class_sa from t_stud_atte_j432 where t_stud_atte_j432.sno=cur_atte.sno;

select class_b into class_sb from t_stud_atte_j432 where t_stud_atte_j432.sno=cur_atte.sno;

select class_c into class_sc from t_stud_atte_j432 where t_stud_atte_j432.sno=cur_atte.sno;

select class_d into class_sd from t_stud_atte_j432 where t_stud_atte_j432.sno=cur_atte.sno;

if(time_min>cur_atte.nowdate)then--通过比较日期,来获取每个学生不同的考勤时间段

time_min:=cur_atte.nowdate;

end if;

if(time_max<cur_atte.nowdate)then

time_max:=cur_atte.nowdate;

end if;

 

if(cur_atte.class12='A')then--以下if判断都是对每节课状态判断,相应次数加一

class_sa:=class_sa+1;

elsif(cur_atte.class12='B')then

class_sb:=class_sb+1;

elsif(cur_atte.class12='C')then

class_sc:=class_sc+1;

elsif(cur_atte.class12='D')then

class_sd:=class_sd+1;

end if;

 

if(cur_atte.class34='A')then

class_sa:=class_sa+1;

elsif(cur_atte.class34='B')then

class_sb:=class_sb+1;

elsif(cur_atte.class34='C')then

class_sc:=class_sc+1;

elsif(cur_atte.class34='D')then

class_sd:=class_sd+1;

end if;

 

if(cur_atte.class56='A')then

class_sa:=class_sa+1;

elsif(cur_atte.class56='B')then

class_sb:=class_sb+1;

elsif(cur_atte.class56='C')then

class_sc:=class_sc+1;

elsif(cur_atte.class56='D')then

class_sd:=class_sd+1;

end if;

 

if(cur_atte.class78='A')then

class_sa:=class_sa+1;

elsif(cur_atte.class78='B')then

class_sb:=class_sb+1;

elsif(cur_atte.class78='C')then

class_sc:=class_sc+1;

elsif(cur_atte.class78='D')then

class_sd:=class_sd+1;

end if;

 

if(cur_atte.class90='A')then

class_sa:=class_sa+1;

elsif(cur_atte.class90='B')then

class_sb:=class_sb+1;

elsif(cur_atte.class90='C')then

class_sc:=class_sc+1;

elsif(cur_atte.class90='D')then

class_sd:=class_sd+1;

end if;

 

class_res:=100-class_sb*2-class_sc*5-class_sd;--重新计算考勤成绩

--将相关数据更新到学生考勤表

update t_stud_atte_j432 set t_stud_atte_j432.startdate=time_min where t_stud_atte_j432.sno=cur_atte.sno;

update t_stud_atte_j432 set t_stud_atte_j432.stopdate=time_max where t_stud_atte_j432.sno=cur_atte.sno;

update t_stud_atte_j432 set t_stud_atte_j432.class_a=class_sa where t_stud_atte_j432.sno=cur_atte.sno;

update t_stud_atte_j432 set t_stud_atte_j432.class_b=class_sb where t_stud_atte_j432.sno=cur_atte.sno;

update t_stud_atte_j432 set t_stud_atte_j432.class_c=class_sc where t_stud_atte_j432.sno=cur_atte.sno;

update t_stud_atte_j432 set t_stud_atte_j432.class_d=class_sd where t_stud_atte_j432.sno=cur_atte.sno;

update t_stud_atte_j432 set t_stud_atte_j432.result=class_res where t_stud_atte_j432.sno=cur_atte.sno;

--将成绩更新到学生表

update t_stud_j432 set t_stud_j432.sum_evaluation=class_res where t_stud_j432.sno=cur_atte.sno;

end loop;--直到遍历完整张考勤表

end;

/

show error

 

3.触发器tg_attend_j432分析

create or replace trigger tg_attend_j432

after insert or update or delete on t_attend_j432

begin

p_stud_atte_j432;--每次更改考勤表的数据,就重新汇总一次学生考勤表的数据

end;

/

show error

四、实验总结及改进

    本次实验最大的问题就是关于建表,有横表和竖表的建表方案,我是按照横标来建的,将属性值当成了属性,导致考勤表出现数据冗余(大量没课状态E)以及使得统计过程的复杂度提升,万幸还是做成了,在最后触发器那,每对考勤表就行一次操作,就从重新统计一次数据,如果数据量很大,会使得效率很低而且不合理,有待改进。

横表建表方式
学号 时期 姓名 第一节课 第二节课 第三节课 第四节课 第五节课
0101 10.1 张三 正常 正常 请假 正常 缺勤
0102 10.2 李四 缺勤 正常 迟到 正常 正常
竖表建表方式
学号 姓名 日期 第几节课 状况
0101 张三 10.1 3 请假
0101 张三 10.1 5 缺勤
0102 李四 10.2 1 缺勤

猜你喜欢

转载自blog.csdn.net/y_dd6011/article/details/86344734