在学习触发器以及存储过程中时遇到了一些典型的例题,在这里和大家分享一下。
码字不易,点个关注给个赞吧
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. 利用触发器,在星期一、周末及每天下班时间(每天9:00以前、18:00以后)后不允许更新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);
运行结果即如图所示,会启用报错程序
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;
其运行结果如图所示,并非运行错误
创建触发器,对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 未经允许,禁止转载