Oracle触发器(trigger):一般用法
trigger和procedure,function類似,只不過它不能被顯示調(diào)用,只能被某個(gè)事件觸發(fā)然后Oracle自動(dòng)去調(diào)用.常用的一般是針對一個(gè)表或視圖創(chuàng)建一個(gè)trigger,然后對表或視圖做某些操作時(shí)觸發(fā)trigger.當(dāng)然除此之外還有,schema,database級別的trigger.
什么樣的操作觸發(fā)trigger
常見的是DML(insert,update,delete) , DDL(create,alter,drop)語句.
不常見的是schema級別trigger在session連接或斷開時(shí)觸發(fā).database級別trigger在系統(tǒng)啟動(dòng)或退出時(shí)觸發(fā).
你可能很容易發(fā)現(xiàn)如果是select查詢操作就沒法用到trigger,而有時(shí)可能我們想監(jiān)測誰查看了一些敏感信息,此時(shí)只能用到一個(gè)叫FGA的東東,可以創(chuàng)建一個(gè)審計(jì)策略(可以看成加強(qiáng)版的trigger,FGA介紹詳見:?http://www.linuxidc.com/Linux/2013-06/86603.htm?)?
使用觸發(fā)器注意事項(xiàng)
1.觸發(fā)器不接受參數(shù),一個(gè)表最多可有12個(gè)觸發(fā)器(觸發(fā)器類型剛好是12種),并且同一時(shí)間,同一事件,同一類型的觸發(fā)器只能有一個(gè)(保證觸發(fā)器操作不沖突嘛).
2.觸發(fā)器最大為32KB,由于大小受到限制自然也不能使用long,blob這樣的大變量.如果實(shí)在是有復(fù)雜的邏輯,要弄個(gè)很復(fù)雜的觸發(fā)器,可以通過procedure或function實(shí)現(xiàn)一部分功能,然后調(diào)用
3.因?yàn)橛|發(fā)器實(shí)際上可以看作觸發(fā)語句的一部分.所以得遵循一些約束條件,比如不能有事務(wù)控制語句(commit,rollback,savepoint),DDL語句.為啥子呢,這些特殊語句與一般sql語句的最主要區(qū)別是涉及到commit的問題.所以如果觸發(fā)語句只是一般語句的話自然不能因?yàn)閠rigger的操作帶有commit這樣的特性了.?
創(chuàng)建觸發(fā)器
針對表或視圖的觸發(fā)器格式如下:?
CREATE [OR REPLACE] TRIGGER trigger_name
{BEFORE | AFTER }
{INSERT | DELETE | UPDATE [OF column [, column …]]}
[OR {INSERT | DELETE | UPDATE [OF column [, column …]]}...]
ON [schema.]table_name | [schema.]view_name
[REFERENCING {OLD [AS] old | NEW [AS] new| PARENT as parent}]
[FOR EACH ROW ]
[WHEN condition]
PL/SQL_BLOCK | CALL procedure_name;
?
先來看一個(gè)簡單的,statement級別的trigger怎么創(chuàng)建.假如有表tb1,每insert一點(diǎn)就通過trigger在tblog中記錄一些信息.
create or replace trigger?tb1_trigger
after insert on?tb1
referencing new?as new?old?as old
?
declare
v_info varchar2(100);
begin
v_info := "do a insert";
insert into tblog(info) values(v_info);
end;
?
trigger的創(chuàng)建中有個(gè)不太容易理解的內(nèi)容:一針對row級別的trigger舊值新值問題
row級別trigger舊值新值
針對一個(gè)表或視圖創(chuàng)建trigger時(shí)分為statement級別與row級別的trigger.所謂statement級別是說一個(gè)sql語句觸發(fā)一次trigger,而如果是row級別則一個(gè)sql語句涉及到多行數(shù)據(jù)則trigger會(huì)被觸發(fā)多次.
而舊值就是指要更改的那一行數(shù)據(jù)在被改之前的值,新值就是用戶更新后值.假如表tt只有一列一行數(shù)據(jù):88.然后用戶執(zhí)行語句update tt set id = 99 where id = 88;
則舊值指88,新值指99.那你們可能會(huì)問用什么方式去得到舊值或新值啊.來舉例看下
假如有表tb(eno int); 和表tblog( info varchar2(100)); 假如在tb上創(chuàng)建trigger,tb每update一次則在tblog中記錄舊值就更改后的新值.
?
CREATE OR REPLACE TRIGGER tb_trigger
BEFORE UPDATE
ON tb
REFERENCING NEW AS new_val OLD AS old_val --在這里設(shè)置名字,然后可引用新值,舊值.如果不指定默認(rèn)值為new ,old.可以通過:new或:old去引用
FOR EACH ROW
DECLARE
v_info varchar2(100);
BEGIN
?
v_info := 'old value:' ||to_char(?:old_val.eno) || 'new value:' || to_char(:new_val.eno);
insert into tblog values(v_info);
END;
條件判斷
假如只有在涉及到某一行的操作時(shí)觸發(fā)trigger,假如該觸發(fā)器是針對updat,delete,insert都觸發(fā)的情形.咋整呢,自然是多用些when去判斷啊.
例如
CREATE OR REPLACE TRIGGER tb_trigger
BEFORE UPDATE or insert or delete
ON tb
REFERENCING NEW AS new_val OLD AS old_val --在這里設(shè)置名字,然后可引用新值,舊值
FOR EACH ROW
when (old_val.eno = 99)
DECLARE
v_info varchar2(100);
BEGIN
?
case
when updating then
v_info := 'old value:' ||to_char( :old_val.eno) || 'new value:' || to_char(:new_val.eno);
insert into tblog values(v_info);
?
when inserting then
null;
?
when deleting then
null;
?
end case;
END;
總結(jié)
以上是生活随笔為你收集整理的Oracle触发器(trigger):一般用法的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: oracle利用触发器实现自增列
- 下一篇: oracle触发器的类型及使用方法