觸發器詳解


1. 觸發器的概念:

觸發器是存儲在服務器中的程序單元,當數據庫中某些事件發生時(比如insert\update\delete),數據庫自動啟動觸發器,執行觸發器中的相應操作。

(1) 觸發器是一種特殊的存儲過程,具備事務的功能;

(2) 觸發器不能被直接調用,而是由事件來觸發;--例如:增刪改

(3) 觸發器常用於加強數據的完整性約束和業務規則等。

簡單點說:觸發器就是個開關,燈就是開關觸發后的操作,觸動了開關燈就亮了。

2. 觸發事件:

Insert,update,delete,create(創建對象時),alter,drop

logon/logoff(用戶的登錄或注銷時執行觸發器)

startup/shutdown(數據庫打開或關閉時執行觸發器)。

3. 觸發時間

before 在指定的事件發生之前執行觸發器

after 在指定的事件發生之后執行觸發器

4. 觸發級別

4.1行級觸發

行觸發:對觸發事件影響的每一行執行觸發器,即觸發機制是基於行的。改一行數據,觸發一次。

關鍵語句:for each row

--案例1

create or replace tirgger t_mydel

after delete

on stuinfo

for each row

begin

dbms_output.put_line('刪的好!');

end;

--執行(刪除了一條記錄,結果顯示一條'刪的好')

delete from stuinfo where stuname='李文才';

--執行(刪除了整個表中的記錄,顯示N條'刪的好')

delete from stuinfo

--說明:這就是講解行級觸發器。

--行級觸發器:一條條的刪,刪一條就觸發一個行級觸發器。

--語句級觸發器:執行一條觸發一次。

4.2語句觸發

語句觸發:對觸發事件只能觸發一次,而且不能該問受觸發器影響的每一行的值。既無論這條SQL語句影響多少條記錄,觸發器都只觸發一次。

4.2.1. 創建觸發器

create [or replace] trigger trigger_name

after|before|instead of --instead反向

[insert][[or] update [of 列列表]][[or] delete]

on table表或view

[for each row] --行級模式

Begin

--pl/sql語句(begin...end)

End;

案例1:

--創建一個觸發器tig_1,當用戶刪除scott.emp表中的數據時提示。

SQL>create or replace trigger tig_1

after delete

on scott.emp //注意:這里沒有用for each row,即不管刪除多少條,只觸發一次該觸發器

begin

if deleting then

dbms_output.put_line('有用戶刪除了emp表中的數據!');

end if;

end;

案例2:

--創建一個觸發器tig_2,當表scott.dept中的deptno列的值發生變化時,自動更新表scott.emp中的deptno列的值,從而保證數據的完整性。

SQL>create or replace trigger tig_2

after update

on scott.emp

for each row

begin

update scott.emp set deptno = :new.deptno

where deptno = :old.deptno;

end;

注意:

這段程序中有兩個概念:new和:old, :new代表執行更新操作之后的新表,:old代表執行更新操作之前的舊表。

通過這兩張表的使用,可以訪問到觸發器執行前后表數據的變化。

insert操作只有:new,delete操作只有:old,update操作二者皆有。

:new 和 :old只用於行級觸發器。

--:new表,將插入的數據先放入到:new表中,確認后放到要更新的表。

--:old表,將不要的數據先放入到:old表中,確認不要了再清除:old表。

--注意::new表和:old表中至始至終就只有一條數據,那請問有多少個列?觸發器的表有多少個列,:new表和:old表就有多少個列。

--案例:

SQL>insert into emp values(…,張三,…,0,……);

SQL>create or replace trigger trig_name

after insert --插入操作之后

on emp --在emp表中

for each row --行級模式

begin

if(:new.sal<=0) then --新表:new中的sal等於0

dbms_output.put_line('警告:干活不能不給薪水');

rollback;(可以用異常:拋異常后回滾數據)

else

dbms_output.put_line('已插入記錄');

commit;

end if;

end;

5.觸發器組成三部分:

a. 觸發器語句(事件)--定義激活觸發器的DML事件和DDL事件;

b. 觸發器限制 --執行觸發器的條件,該條件為真才能激活觸發器;

c. 觸發器操作(主體)--包含SQL語句和代碼,它們在發出了觸發語句且觸發限制的值為真是才運行。

注示:序列通過前觸發保存到數據庫中。

案例:在級聯表中創建觸發器案例

--李斯文不能刪

(什么時候觸發?a.delete時; b.when 條件滿足時; c.代碼中寫明)

SQL>create or replace trigger t_studel

after delete --刪除操作之后

on stuinfo

for each row

begin

if :old.stuname='李斯文' then --如果:old表中存在李斯文,就提示不能刪

--拋出異常

raise_application_error(-20010,'該學生不能刪!!!');

end if;

end;

SQL>delete from emp;

--李斯文不能刪也不能改

只需修改上例代碼中的:

……

after delete or update

……

--怎么知道是(insert\delete\update)哪個操作?不知道沒關系,用case when語句

……

begin

case

when deleting then

--刪除時

if :old.stuname='李斯文' then

raise_application_error(-20010,'該學生不能刪!!!');

end if;

when updating then

--修改時

if :old.stuname='李斯文' then

raise_application_error(-20011,'該學生不能修改!!!');

end if;

when inserting then

--插入時

if :new.stuname='張楊' then

raise_application_error(-20012,'該學生你也敢招!!!');

end if;

end case;

end;

6.多表連接觸發器

在stuinfo表中寫個delete觸發器,指定刪除的人名,

直接刪除stumarks表中該人的成績。

create or replace tirgger t_mydel

after delete

on stuinfo

for each row

declare

stu varchar2(22);

begin

stu:=:old.stuno; --將刪除的學生的學號賦值給該變量

delete from stumarks where stuno=stu;

end;

--運行下

delete from stuinfo where stuname='李斯文';

7. 觸發器的應用(標識列):

標識列:序列+觸發器

--解決:

(1)建表

create table tb_715(

sid number,

sname varchar2(22)

)

(2)創建序列

create sequence seq715;

(3)創建個觸發器,用前觸發,用new表

create or replace trigger t_insert

before insert

on tb_715

for each row

begin

--新表中的id=序列的下一個值

:new.sid:=seq715.nextval;

end;

*****************************************

oracle 11g的語法:

:new.sid:=seq715.nextval;

oracle 10g的語法:

select seq715.nextval into :new.sid from dual;

別用變量,用變量的方法就是11g的寫法。

Oracle觸發器分:前觸發、后觸發


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM