在學習觸發器以及存儲過程中時遇到了一些典型的例題,在這裡和大家分享一下。
碼字不易,點個關注給個贊吧
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);