日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Oracle触发器简单使用记录

發布時間:2024/7/5 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Oracle触发器简单使用记录 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

在ORACLE系統里,觸發器類似函數和過程。
1、觸發器類型:(一般為:語句級觸發器和行級觸發器。)
1)、DML觸發器: 創建在表上,由DML事件引發
2)、instead of觸發器: 創建在視圖上并且只能在行級上觸發,用于替代insert,delete等操作(由于oracle中不能直接對有兩個以上的表建立的視圖進行DML操作,所以給出替代觸發器,它是專門為進行視圖操作的一種處理方法)
3)、DDL觸發器: 觸發事件時數據庫對象的創建和修改
4)、數據庫事件觸發器:定義在數據庫或者模式上,由數據庫事件觸發

語法:
create or replace trigger 觸發器名
<before | after | instead of> <insert | update | delete>--<insert | update | delete>可以選擇一個或多個DML語句,如果選擇多個,則用or分開,如:insert or update。
on 表名或者視圖名或者用戶名或者數據庫名
[for each row] [觸發級別]針對一個表或視圖創建trigger時分為statement級別與row級別的trigger.所謂statement級別是說一個sql語句觸發一次trigger,而如果是row級別則一個sql語句涉及到多行數據則trigger會被觸發多次
when(condition)[when判斷條件]
[declare 變量] 11g
begin
pl/sql語句;
end 觸發器名;
(注:代碼涉及到對關聯表的數據操作,在行級觸發器中使用,將會報ORA-04091錯誤。這時可以通過自制事務來規避,弊端是使用自制事務后無法回滾rollback)
觸發時間:before/after 在指定的事件發生之前/后執行觸發器 instead of 觸發器用在對視圖的更新上。
觸發事件:Insert,update,delete,create(創建對象時),alter,drop,logon/logoff(用戶的登錄或注銷時執行觸發器),startup/shutdown(數據庫打開或關閉時執行觸發器)。
常見的是DML(insert,update,delete) , DDL(create,alter,drop)語句
觸發級別:for each row(行級觸發)對觸發事件影響的每一行執行觸發器,即觸發機制是基于行的。改一行數據,觸發一次。
不寫為語句觸發(對觸發事件只能觸發一次,而且不能該問受觸發器影響的每一行的值。既無論這條SQL語句影響多少條記錄,觸發器都只觸發一次。)
WHEN后跟的condition:是觸發器的響應條件,只對BEFORE和AFTER行級觸發器有效,當操作的記錄滿足condition時,觸發器才被執行,否則不執行。Condition中可以通過new對象和old對象不帶“:”(注意區別于前面的:new和:old,在代碼中引用需要加上冒號)來引用操作的記錄。

2、簡例
創建測試用表:
create table emp_bak1 as select * from emp;
create table emp_bak2 as select * from emp;

例1:

create or replace trigger insert_empafter insert on emp_bak1for each row declare --Declare后面跟的是本地變量定義部分,如果沒有本地變量定義,此部分可以去掉test_val emp_bak1.ename%type;--根據表的字段定義變量類型 begindbms_output.put_line('員工編號:'||:new.empno);dbms_output.put_line('員工姓名:'||:new.ename);dbms_output.put_line('職位:'||:new.job);dbms_output.put_line('工資:'||:new.sal);dbms_output.put_line('所在部門:'||:new.deptno);dbms_output.put_line('---觸發器已被執行---');--select ename into test_val from emp_bak1 where empno = 7839;--ORA-04091select :new.empno into test_val from dual;dbms_output.put_line('---測試--->'||test_val); end;insert into emp_bak1 (empno, ename, job, sal, deptno) values ('666', 'SM', 'IT', '800', '20');

oracle默認的 用old代表老數據 new代表新數據(這兩個變量只有在使用了關鍵字 "FOR EACH ROW"時才存在;referencing new as new_val old as old_val:這個可以更改新舊值的名字來引用新值,舊值)
insert時 只有new 沒有old
delete時 只有old 沒有new
update時 二者都可用

create or replace trigger delete_empbefore delete on emp_bak1 --刪除操作前觸發for each row begininsert into emp_bak2(empno, ename, job, sal, deptno)values(:old.empno, :old.ename, :old.job, :old.sal, :old.deptno);dbms_output.put_line('-----有數據刪除,員工號為'||:old.empno||'詳細信息見emp_bak2表------'); end delete_emp;insert into emp_bak1 (empno, ename, job, sal, deptno) values ('777', 'K', 'TE', '1000', '30'); delete from emp_bak1 where empno = 777;

例2:指定條件列觸發

create or replace trigger tri_01after insert or update of sal on emp_bak1for each row beginif inserting thendbms_output.put_line('新人入駐有收入sal');elsif updating thendbms_output.put_line('sal有變動');end if; end tri_01;update emp_bak1 set sal = 888 where empno = 7934;--觸發 update emp_bak1 set comm = 666 where empno = 7934;--未觸發

注:第二行中的of sal on emp_bak1 是在表emp_bak1的sal字段發生變更時才觸發操作,
在觸發器主體的if語句表達式中,inserting, updating和deleting可以用來區分當前是在做哪一種DML操作,可以作為把多個類似觸發器合并在一個觸發器中判別觸發事件的屬性。

例3:when條件限制

create or replace trigger tri_02before update of sal, comm or delete on emp_bak1for each rowwhen (old.deptno = 30) --注:old前不帶':'且結尾不帶';' begincasewhen updating('sal') thendbms_output.put_line('原來薪資:'||:old.sal||';變更后薪資:'||:new.sal||';');if :new.sal < :old.sal thendbms_output.put_line('降薪不被允許');raise_application_error(-20001, '部門30的人員的工資不能降');end if;when updating('comm') thendbms_output.put_line('原來獎金:'||:old.comm||';變更后獎金:'||:new.comm||';');if :new.comm < :old.comm thendbms_output.put_line('降獎金不被允許');raise_application_error(-20002, '部門30的人員的獎金不能降');end if;when deleting thenraise_application_error(-20003, '部門30的人員不能刪');end case; end;

select * from emp_bak1 where deptno = 30;
update emp_bak1 set comm = 2000 where empno = 7499;
update emp_bak1 set sal = 20000 where empno = 7698;

raise_application_error相當于拒絕了插入或者修改事務
oracle允許自定義的錯誤代碼的范圍為-20000-->20999
raise_application_error(-20001,'ErrorCode');

例4:instead of觸發器
instead of 選項使ORACLE激活觸發器,而不執行觸發事件。只能對視圖和對象視圖建立instead of觸發器,而不能對表、模式和數據庫建立instead of 觸發器。

--語法類似: create [or replace] trigger trigger_name instead of {insert | delete | update [of column [, column …]]} on view_name --只能定義在視圖上 [referencing {old [as] old_val | new [as] new_val| parent as parent}]--可以給old/new對象賦予新的名稱(可以不要) [for each row ] --因為instead of觸發器只能在行級上觸發,所以沒有必要指定 [when condition] pl/sql_block | call procedure_name;

視圖創建

create view view_emp as select deptno,count(*) count_no,sum(sal) sal from emp group by deptno;


對基表處理過的視圖,在刪除時會報下面的錯誤
ORA-01732: 此視圖的數據操縱操作非法
此時可以創建INSTEAD_OF觸發器來為 DELETE 操作執行所需的處理,即刪除EMP表中所有基準行

create or replace trigger view_tri_03instead of delete on view_empfor each row begindelete from emp where deptno= :old.deptno;dbms_output.put_line('從emp基表中刪除部門編號為:'||:old.deptno||'的基礎人員數據。'); end view_tri_03;

可看出此觸發器只是觸發了一個刪除部門號的事件,實際更改的還是基表。

例5:語句級觸發器

create or replace trigger tri_04 after insert or update of sal on emp_bak1 declarev_sumsal number; beginselect sum(sal) into v_sumsal from emp_bak1;if v_sumsal > 50000 thenraise_application_error(-20001, '總工資超過50000');end if; end;

--如果用行級觸發器(for each row)會報ORA-04091錯誤

insert into emp_bak1 (empno, ename, job, sal, deptno) values ('777', 'K', 'TE', '90000', '30');

?

(注:此為學習記錄筆記,僅供參考若有問題請指正,后續補充......)

?

參考資料:https://www.cnblogs.com/wishyouhappy/p/3665851.html

參考資料:https://blog.csdn.net/weiwenhp/article/details/9179891

參考資料:https://www.cnblogs.com/hyq0002013/p/6085981.html

參考資料:https://blog.csdn.net/IndexMan/article/details/8023740

?

轉載于:https://www.cnblogs.com/shenjie0622/p/10106526.html

總結

以上是生活随笔為你收集整理的Oracle触发器简单使用记录的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。