实验12 触发器与作业.docx

上传人:b****6 文档编号:7759895 上传时间:2023-01-26 格式:DOCX 页数:22 大小:230.97KB
下载 相关 举报
实验12 触发器与作业.docx_第1页
第1页 / 共22页
实验12 触发器与作业.docx_第2页
第2页 / 共22页
实验12 触发器与作业.docx_第3页
第3页 / 共22页
实验12 触发器与作业.docx_第4页
第4页 / 共22页
实验12 触发器与作业.docx_第5页
第5页 / 共22页
点击查看更多>>
下载资源
资源描述

实验12 触发器与作业.docx

《实验12 触发器与作业.docx》由会员分享,可在线阅读,更多相关《实验12 触发器与作业.docx(22页珍藏版)》请在冰豆网上搜索。

实验12 触发器与作业.docx

实验12触发器与作业

实验12 触发器与作业

姓名:

学号:

专业:

班级:

同组人:

实验日期:

【实验目的与要求】

⏹理解什么是触发器

⏹掌握触发器的设计与使用

⏹掌握在Oracle中完成定时作务的方法

【实验内容与步骤】

相关说明:

本实验中前面实验创建的触发器可能对后面的实验产生干扰,若出现这种情况,请把前面触发器删除,再完成后面实验。

建议每完成一个实验题后,即将该题相关的触发器删除,以免对后面实验产生干扰。

12.1触发器创建与删除语法

1.触发器的创建

触发器是一种在发生数据库事件时自动运行的PL/SQL

语法如下:

CREATE[ORREPLACE]TIGGER触发器名触发时间触发事件

ON表名

[FOREACHROW]

BEGIN

pl/sql语句

END

2.触发器的删除

DROPTRIGGERtrigger_name

12.2触发器基础

以下程序展示的是触发器的基本使用方法,请阅读并理解以下程序代码,给出运行结果。

1.创建测试表

--droptableemployees;

createtableemployees(

idnumber(5),

namevarchar2(30),

salarynumber(8,2),

job_idvarchar2(20)

);

2.创建触发器

CREATEORREPLACETRIGGERsecure_emp_1--这里不能有IS

BEFOREINSERTONemployees--这里没有分号

BEGIN

IF(TO_CHAR(SYSDATE,'DY')IN('星期六','星期天')OR(TO_CHAR(SYSDATE,'HH24:

MI')NOTBETWEEN'08:

00'AND'18:

00'))THEN

RAISE_APPLICATION_ERROR(-20500,'你只能在工作时间对表进行操作');

ENDIF;

END;

/

3.测试触发器

(1)--测试语句

insertintoemployeesvalues(1,'a',2222,'aaaaa');

给出测试结果截图:

(2)将系统时间修改为周六,再Insert一条记录,给出并比较两次运行的结果。

给出测试结果截图:

12.3使用触发器监控数据更新操作

阅读以下程序,理解程序功能,给出运行测试结果。

1.创建触发器

CREATEORREPLACETRIGGERsecure_emp_2

BEFOREINSERTORUPDATEORDELETEONemployees

BEGIN

--如果当前时间是周六或周日或者时间不在8:

00-18:

00之间

IF(TO_CHAR(SYSDATE,'DY')IN('星期五','星期天')OR(TO_CHAR(SYSDATE,'HH24:

MI')NOTBETWEEN'08:

00'AND'18:

00'))

THEN

IFDELETINGTHEN

RAISE_APPLICATION_ERROR(-20502,'你只能在工作时间删除员工表的数据');

ELSIFINSERTINGTHEN

RAISE_APPLICATION_ERROR(-20500,'你只能在工作时间插入员工表的数据.');

ELSIFUPDATING('SALARY')THEN

RAISE_APPLICATION_ERROR(-20503,'你只能在工作时间更新员工表的数据');

ELSE

RAISE_APPLICATION_ERROR(-20504,'你只能在工作事件操作员工表的数据.');

ENDIF;

ENDIF;

END;

/

2.运行测试

分别运行以下测试语句,给出运行结果。

并理解为什么会有这样的结果。

insertintoemployeesvalues(1,'a',2222,'AD_PRES');

insertintoemployeesvalues(2,'b',2222,'AD_VP');

给出测试结果截图:

deletefromemployees;

给出测试结果截图:

updateemployeessetsalary=3000;

给出测试结果截图:

12.4在insert或update中使用:

new

阅读并理解以下程序,理解其功能,给出运行测试结果。

1.创建触发器

--在insert或update中使用:

new--

CREATEORREPLACETRIGGERrestrict_salary

BEFOREINSERTORUPDATEOFsalaryONemployees

FOREACHROW

BEGIN

--插入和修改可以使用:

new来访问新的数据,修改也可以使用:

old来访问旧的数据

IFNOT(:

NEW.job_idIN('AD_PRES','AD_VP'))

AND:

NEW.salary>15000

THEN

RAISE_APPLICATION_ERROR(-20202,'员工不能赚到这么多薪水');

ENDIF;

END;

2.运行测试

--测试语句

insertintoemployeesvalues(1,'a',20000,'AD_PRES');

insertintoemployeesvalues(2,'b',20000,'AD_VPs');

updateemployeessetsalary=30000,job_id='xxxx'wherename='a';

给出运行结果:

 

思考:

观察运行结果,比较insert和update语句执行的差别。

12.5在delete中使用:

old

阅读并理解以下程序,理解其功能,给出运行测试结果。

1.创建触发器

CREATEORREPLACETRIGGERrestrict_salary_del

BEFOREDELETEONemployeesFOREACHROW

BEGIN

--在delete语句中只能使用:

old来访问旧的数据

IF(:

OLD.job_idIN('AD_PRES','AD_VP'))AND(:

OLD.salary>15000)

THEN

RAISE_APPLICATION_ERROR(-20202,'该员工不可以删除');

ENDIF;

END;

2.运行测试

--测试语句

insertintoemployeesvalues(2,'张三',20000,'AD_PRES');

deletefromemployeeswherename='张三';

给出运行结果:

12.6INSTEADOF类型的触发器

阅读并理解以下程序,理解其功能,给出运行测试结果。

1.准备工作:

创建触发器及相应测试用表

--INSTEADOF类型的触发器

droptabledepartments;

createtabledepartments(

dept_idnumber(5)primarykey,

dept_namevarchar2(20)

);

droptableemployees;

createtableemployees(

employee_idnumber(5),

employee_namevarchar2(20),

department_idnumber(5),

constraintempl_dept_fkforeignkey(department_id)referencesdepartments(dept_id)

);

--创建视图

createorreplaceviewv_emp

as

selecte.employee_id,e.employee_name,e.department_id,d.dept_name

fromemployeese,departmentsd

wheree.department_id=d.dept_id

--创建触发器

createorreplacetriggernew_view_emp_dept

insteadofinsertonv_emplforeachrow

begin

ifinsertingthen

insertintodepartments

values(:

new.department_id,:

new.dept_name);

insertintoemployees

values(:

new.employee_id,:

new.employee_name,:

new.department_id);

endif;

end;

2.运行测试

(1)查询视图:

select*fromv_emp;

给出运行结果:

(2)插入测试数据

--向视图中插入数据

insertintov_empvalues(171,'张六',1000,'销售部');

(3)结果测试

select*fromemployees;

给出运行结果:

select*fromdepartments;

给出运行结果:

12.7系统级触发器

阅读并理解以下程序,理解其功能,给出运行测试结果。

1.创建触发器

------------系统触发器---------------------------------------

--创建登陆或者退出数据库日志表

droptablelogs;

createtablelogs(

useridvarchar2(20),

timesdate,

opvarchar2(10)–操作类型

);

----登陆数据库触发器

createorreplacetriggerlog_on

afterlogononschema

begin

insertintologsvalues(user,sysdate,'logon');

end;

/

--退出数据库触发器

createorreplacetriggerlog_off

beforelogoffonschema

begin

insertintologsvalues(user,sysdate,'logoff');

end;

/

2.运行测试

(1)--以不同的用户身份登录和退出数据库数次,以获得相关数据

 如:

connsys/testdbassysdba;

Connsoctt/tiger

(2)--A设置日期的显示格式

altersessionsetnls_date_format='YYYY-MM-DDHH_MI_SS';

(3)--查看记录

select*fromlogs;

给出运行结果:

12.8作业与定时任务

12.7.1作业概述

作业是Oracle中一个程序包,可用于Oracle中实现定时任务。

日常开发最常用到的用于完成定时任务的是Job中包中的,submit函数,其接口如下:

1.dbms_job.submit(joboutbinary_integer,  

2.what       in   archar2,  

3.next_date    in   date,  

4.interval     in   varchar2,  

5.no_parse     in   boolean)  

其中:

●job:

输出变量,是此任务在任务队列中的编号;

●what:

执行的任务的名称及其输入参数;

●next_date:

任务执行的时间;

●interval:

任务执行的时间间隔。

其中Interval这个值是决定Job何时,被重新执行的关键;当interval设置为null时,该job执行结束后,就被从队列中删除。

假如我们需要该job周期性地执行,则要用‘sysdate+m’表示。

以下实验中创建一个名称为tri_test_id的触发器,用于实现当在作业中定时调用存储过程,向Test表插入数据时,自动的触发序列号的产生,并添加数据到Test表中。

更新员工工资之后,将更新纪录保存到表salary_change_record中。

12.7.2实验准备

--

(1)创建测试表:

CREATETABLETest(idnumber,cur_uservarchar2(20),cur_timevarchar2(30));

--

(2)创建序列test_sequence:

CREATESEQUENCEtest_sequence

INCREMENTBY1--每次加几个

STARTWITH1--从1开始计数

NOMAXVALUE--不设置最大值

NOCYCLE--一直累加,不循环

CACHE10;

--建触发器tri_test_id:

CREATEORREPLACETRIGGERtri_test_id

beforeINSERT

ONtest--test是表名

FOReachrow

DECLARE

nextidnumber;

BEGIN

IF:

new.idISNULLor:

new.id=0THEN--id是列名

SELECTtest_sequence.nextval--test_sequence正是刚才创建的序列

INTOnextid

FROMsys.dual;

:

new.id:

=nextid;

ENDIF;

ENDtri_test_id;

/

--创建一个自定义过程

CREATEORREPLACEPROCEDUREproc_test

AS

BEGIN

INSERTINTOtest(cur_user,cur_time)

VALUES(user,to_char(sysdate,'YYYY-MM-DDHH24:

MI:

SS'));--系统时间转为格式串

END;

/

12.7.3作业的创建与使用

--创建JOB

DECLAREjobNonumber;

BEGIN

dbms_job.submit(

jobNo,--job参数

'proc_test;',--what参数是将被执行的PL/SQL代码块

sysdate,--next_date,参数指识何时将运行这个工作,本例为马上开始

'sysdate+1/(24*60*10)'--interval参数,即1/10分钟运行test过程一次

);--no_parse参数,无

END;

--next_date,可如:

to_date('20110517093500','yyyy-mm-ddhh24:

mi:

ss'),

12.7.4测试

--测试:

1分钟后查看Test表中数据

SELECT*

FROMtest

请给出运行结果:

 

12.7.5停止与移除作业

若要移除、停止或启用作业,需根据作业号,调用作业包中存储过程dbms_job.remove(jobNo)来完成。

其中,作业号可通过数据字典all_jobs获取。

1.获取作业号

可通过查询数据字典all_jobs来获取作业号,示例如下:

其中,job字段值即为作业号。

2.移除作业

--删除JOB

begin

dbms_job.remove(jobNo); --jobNo为作业号,使用时应用查询得到的结果

end;

/

3.停止一个JOB

execdbms_job.broken(jobNo,true)--jobNo为作业号,使用时应用查询得到的结果

4.停止一个JOB

execdbms_job.broken(jobNo,false)--jobNo为作业号,使用时应用查询得到的结果

 

12.9实验练习

1. 实验练习:

利用触发器追踪薪水变动情况

  请创建一个名称为change_record的触发器,实现当对emp表更新员工工资之后,将更新纪录保存到表salary_change_record中。

具体要求如下:

建立日志对薪水的变动情况形成一个追踪,也就是说,如果对某个职员的薪水进行变更就应该将其相应的变更记录全部记下来,将数据记录到表salary_change_record(empid,old_salary,new_salary,change_date)中,其中old_salary:

用来纪录员工原来的工资,new_salary:

用来纪录更新后的工资,change_date:

记录更新的系统时间。

请给出相应的代码:

在emp表中添加或修改几行数据,而后查看表salary_change_record中数据。

请给出测试结果:

2.编写一个数据库触发器,当任何时候某个部门从"dept"中删除时,该触发器将从"emp"表中删除该部门的所有雇员记录。

给出相应的代码:

给出测试结果:

3.映射emp表中每个部门的总人数和总工资

(1)--创建映射表

CREATETABLEdept_sal

AS

SELECTdeptno,COUNT(empno)AStotal_emp,SUM(sal)AStotal_sal

FROMemp

GROUPBYdeptno;

DESCdept_sal;

(2)--创建触发器,映射emp表中每个部门的总人数和总工资

创建一触发器,当emp表中数据改变时,自动修改dept_sal表中数据,使其反映出Emp表中数据的最新状态。

请给出程序源码:

createorreplacetriggerup_emp

afterupdateordeleteorinsertonempforeachrow

declare

t_depnonumber;

t_salnumber;

t_empnumber;

t_nonumber;

begin

ifupdatingthen

t_depno:

=:

old.deptno;

selectcount(empno),sum(sal)

intot_sal,t_emp

fromemp

wheredeptno=t_depno;

updatedept_salsettotal_emp=t_emp,total_sal=t_salwheredeptno=t_depno;

elsifinsertingthen

t_depno:

=:

new.deptno;

selectcount(*)

intot_no

fromemp

wheredeptno=t_depno;

if(t_no)<2then

selectcount(empno),sum(sal)

intot_sal,t_emp

fromemp

wheredeptno=t_depno;

insertintodept_sal

values(t_depno,t_emp,t_sal);

else

selectcount(empno),sum(sal)

intot_sal,t_emp

fromemp

wheredeptno=t_depno;

updatedept_salsettotal_emp=t_emp,total_sal=t_salwheredeptno=t_depno;

endif;

elsifdeletingthen

t_depno:

=:

old.deptno;

selectcount(*)

intot_no

fromemp

wheredeptno=t_depno;

if(t_no)>0then

selectcount(empno),sum(sal)

intot_sal,t_emp

fromemp

wheredeptno=t_depno;

updatedept_salsettotal_emp=t_emp,total_sal=t_salwheredeptno=t_depno;

else

deletefromdept_salwheredeptno=t_depno;

endif;

endif;

end;

/

 

(3)测试

按下面步骤完成测试,结出测试结果,并比对测试结果,看是否满足要求。

A.查询dept_sal中数据:

SELECT*FROMdept_sal;

B.--对emp表进行DML操作

INSERTINTOemp(empno,deptno,sal)VALUES('123','10',10000);

SELECT*FROMdept_sal;

给出测试结果:

 

DELETEEMPWHEREempno=123;

SELECT*FROMdept_sal;

给出测试结果:

4.定时任务练习:

假设公司要求DBA每隔5分钟(实际运作时,一般为一个月统计一次,实验中为了测试,将时间变短为5分钟)根据emp表统计一次公司员工工资总和,并记录到表Total_salary_Table(count_time,total_salry)中(表中count_time表示统计时间;total_salry表示当前员工工资总和,可由sum(sal)运算得到)。

请根据以上任务需求写出完成该功能的程序代码,并给出测试实例结果。

(1)请给出源程序:

 

(2)测试:

执行作业任务后,对emp表的sal字段进行更新(如修改其数据,添加或删除数据行),约5分钟后,对表Total_salary_Table执行查询,并给出查询结果。

Select*

FromTotal_salary_Table;

请给出运行结果:

 

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 工程科技 > 纺织轻工业

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1