存储过程 触发器

在学习触发器以及存储过程中时遇到了一些典型的例题,在这里和大家分享一下。

码字不易,点个关注给个赞吧

1.       定义过程,根据雇员编号找到雇员姓名及工资。(10分)

代码:

 

create or replace procedure pro_emp2(v_empno in emp.empno%type)
is
v_ename emp.ename%type;
begin
select ename into v_ename from emp where empno=V_empno;//需要使用查询语句方可触发异常。
delete from emp 
where empno=v_empno;
--dbms_output.put_line('已成功删除数据');
exception 
when no_data_found then
dbms_output.put_line('查无此人');

end;

 

 

 

executepro_emp(7566);

2.       创建一个功能为:删除给定职工号的职工信息的存储过程,并调用该存储过程。(10分)

代码:

create or replace procedure pro_emp(var_empno in emp.empno%type)is

begin

delete from emp whereempno=var_empno;

exception  //notfound 异常处理

when no_data_foundthen

dbms_output.put_line('无数据记录');

end;

 

executepro_emp(8888);

 

3.       利用存储过程增加部门信息。(10分)

代码:

create or replace procedure pro_dept(var_deptno in dept.deptno%type,var_dname in dept.dname%type,var_loc in dept.loc%type)is

begin   

 insert into dept(deptno,dname,loc)values(var_deptno,var_dname,var_loc);

 dbms_output.put_line('编号为'||var_deptno||'的部门信息被插入');

end;

 

4.      创建一个过程avg_sal,用于输出emp表中某个部门的平均工资,并在PL/SQL匿名块中调用该过程输出20号部门的平均工资。要求:利用输入输出参数实现。(10分)

代码:

create or replace procedure pro_emp(var_deptno in emp.deptno%type)is

avg_sal emp.sal%type;

begin

 select avg(sal) into avg_sal from emp wheredeptno=var_deptno;

 dbms_output.put_line('编号为'||var_deptno||'的部门的平均工资为'||avg_sal);

 exception

when no_data_foundthen

dbms_output.put_line('无数据记录');

end;

 

 

 

5.      从雇员基本信息表(EMP)中统计各部门(DEPTNO)人数后,将结果输出。

--执行存储过程结果如下图所示:(10分)

代码:

create or replace procedure pro_emp is   //统计各部门说明有多条记录故使用游标

cursor cur_emp isselect deptno ,count(empno) num from emp group by deptno;

begin

for x in cur_emp loop

dbms_output.put_line('部门号 '||x.deptno||'  人数  '||x.num);

end loop;

end;

 

execute pro_emp;

 

 

6.       编写一个“过程”,可以输入一个雇员名,如果该雇员的职位为PRESIDENT就给他的工资增加1000,如果该雇员的职位为MANAGER,就给他的工资加500,其他职位的雇员工资增加200。并在SQL*PLUS中调用该过程来修改FORD的工资。(10分)

代码:

create or replace procedure pro_emp(var_ename in emp.ename%type) is

var_job emp.job%type;

begin

select job intovar_job from emp where ename=var_ename;

dbms_output.put_line('该员工的职务为'||var_job);

if var_job='PRESIDENT' then

update emp setsal=sal+1000 where ename=var_ename; dbms_output.put_line(var_ename||'的工资增加了1000');

elsif var_job='MANAGER' then

update emp setsal=sal+500 where  ename=var_ename;dbms_output.put_line(var_ename||'的工资增加了500');

else update emp setsal=sal+200 where  ename=var_ename;dbms_output.put_line(var_ename||'的工资增加了200');

end if;

 exception

when no_data_foundthen

dbms_output.put_line('无数据记录');

end;

 

 

 

executepro_emp('mldn');

 

7.       利用触发器,在星期一、周末及每天下班时间(每天900以前、1800以后)后不允许更新emp数据表。(10分)

注意:如果想此时验证触发器效果,对上述触发器进行相应修改

代码:

create or replace trigger emp_time

before update or insert or delete

on emp

begin

if

to_char(sysdate,'DY')in('星期一','星期六','星期日') //获取当前系统时间

or to_char(sysdate,'HH24')<'9'

and to_char(sysdate,'HH24')>'18'

then raise_application_error(-20009,'当前时间无法对emp表进行操作');

end if;

end ;

 

 

insert into emp(empno,ename,job,hiredate,sal,comm,mgr,deptno)

 values(8997,'mldn','MANAGER',SYSDATE,2000,500,7369,40);

存储过程 触发器_第1张图片

运行结果即如图所示,会启用报错程序

8.       编写触发器,在每天12点以后,不允许修改雇员工资和奖金。(10分)

代码:

create or replace triggeremp_time1

before update of sal,comm   //针对表中某一属性列作用用of

on emp

begin

if

to_char(sysdate,'HH24')>'8'

then raise_application_error(-20008,'当前时间无法对emp表进行修改工资或奖金的操作操作');//报错处理

end if;

end ;

 

9.       创建一个行级触发器CASCADE_DEL_UPD,当修改部门编号时,EMP表的相关行的部门编号也自动修改;当删除部门表中某个部门号是,EMP表该部门号的员工一并删除。(10分)

 

 

对于INSERT语句, 只有NEW是合法的;

对于DELETE语句,只有OLD才合法;

对于UPDATE语句,NEW、OLD可以同时使用。

 

代码:

create or replace trigger CASCADE_DEL_UPD

before  update of deptno or delete

on dept

for each row

declare

begin

if deleting  then delete from emp where deptno=:old.deptno;  end if;  //如果进行删除操作就先将emp表中的deptno信息删除

if updating then  update emp set deptno=:new.deptno wheredeptno=:old.deptno;  end if;

end CASCADE_DEL_UPD;

 

 

create or replace trigger cas_update
before update of deptno or delete
on dept
for each row
begin
case
when updating('deptno') then update emp set deptno=:new.deptno where deptno=:old.deptno;
else delete from emp where deptno=:old.deptno;
end case;
end;

 

dept表中40号变为60

update dept setdeptno=60 where deptno=40

delete from deptwhere deptno=40;

 

 

10.   创建一个显示员工编号、员工姓名、所在部门号及部门名的视图。利用触发器实现向该视图中添加记录的操作。(10分)

代码:

create view view_emp

as select empno,ename,dept.deptno,dname

from emp,dept

where emp.deptno=dept.deptno;

 

 

create or replace trigger tir_insert_view

instead of insert

on view_emp

for each row

declare

row_deptdept%rowtype;

begin

select * intorow_dept from dept where deptno=:new.deptno;

if sql%notfound then

insert intodept(deptno,dname)

values(:new.deptno,:new.dname);

end if;

insert into emp(empno,ename,deptno)

values(:new.empno,:new.ename,:new.deptno);

end tir_insert_view;

 

 

创建触发器,对emp表中的员工工资只能上涨不能降低

create or replace trigger emp_update

after update of sal

on emp
for each row
begin
if :new.sal<:old.sal then raise_application_error(-20008,'员工工资只能升不能降');
else dbms_output.put_line('员工工资已被提升');
end if;
end;

存储过程 触发器_第2张图片

其运行结果如图所示,并非运行错误

 

 

创建触发器,对emp表中数据进行删除备份

create or replace trigger save_emp

before delete 
on emp
for each row
begin
if deleting then
dbms_output.put_line('已成功将被删除数据备份到empsave表中');
insert into empsave values(:old.empno,:old.ename,:old.job,:old.mgr,:old.hiredate,:old.sal,:old.comm,:old.deptno);
end if;
end;

 

 

create  table empsave as select * from emp where 1=2; //参照emp表建立empsave,但只是使用其属性,不用其数据

delete from emp where empno=8913;




 select * from emp; 
 insert into emp(empno,ename,job,hiredate,sal,comm,mgr,deptno)

  values(8913,'mldn','MANAGER',SYSDATE,2000,500,7369,30);

在表emp中,字段ename标识了当前的员工的姓名。要求新增数据时确保该字段值都为大写形式。
create or replace trigger maxename
before insert or update of ename
on emp 
for each row
begin
if inserting then
:new.ename:=lower(:new.ename);
end if;
end;

 

版权所有 https://blog.csdn.net/pengxiang1998 未经允许,禁止转载

你可能感兴趣的:(数据库)