按照觸發方式,oracle的觸發器分為語句級和行級兩種型別,在檢視上所建立的觸發器叫做什麼型別的觸發器? 匿名使用者 1級 2008-01-20 回答

DML觸發器有三類:

1, insert觸發器;

2, update觸發器;

3, delete觸發器;

觸發器的組成部分:

觸發器的宣告,指定觸發器定時,事件,表名以型別

觸發器的執行,PL/SQL塊或對過程的呼叫

觸發器的限制條件,透過where子句實現

型別:

應用程式觸發器,前臺開發工具提供的;

資料庫觸發器,定義在資料庫內部由某種條件引發;分為:

DML觸發器;

資料庫級觸發器;

替代觸發器;

DML觸發器元件:

1,觸發器定時

2,觸發器事件

3,表名

4, 觸發器型別

5, When子句

6, 觸發器主體

可建立觸發器的物件:資料庫表,資料庫檢視,使用者模式,資料庫例項

建立DML觸發器:

Create [or replace] trigger [模式。]觸發器名

Before| after insert|delete|(update of 列名)

On 表名

[for each row]

When 條件

PL/SQL塊

For each row的意義是:在一次操作表的語句中,每操作成功一行就會觸發一次;不寫的話,表示是表級觸發器,則無論操作多少行,都只觸發一次;

When條件的出現說明了,在DML操作的時候也許一定會觸發觸發器,但是觸發器不一定會做實際的工作,比如when 後的條件不為真的時候,觸發器只是簡單地跳過了PL/SQL塊;

Insert觸發器的建立:

create or replace trigger tg_insert

before insert on student

begin

dbms_output。put_line(‘insert trigger is chufa le 。。。。。’);

end;

/

執行的效果:

SQL> insert into student

2 values(202,‘dongqian’,‘f’);

insert trigger is chufa le 。。。。。

update表級觸發器的例子:

create or replace trigger tg_updatestudent

after update on student

begin

dbms_output。put_line(‘update trigger is chufale 。。。。。’);

end;

/

執行效果:

SQL> update student set se=‘f’;

update trigger is chufale 。。。。。

已更新8行;

可見,表級觸發器在更新了多行的情況下,只觸發了一次;

如果在after update on student後加上

For each row的話就成為行級觸發器,執行效果:

SQL> update student set se=‘m’;

update trigger is chufale 。。。。。

update trigger is chufale 。。。。。

update trigger is chufale 。。。。。

update trigger is chufale 。。。。。

update trigger is chufale 。。。。。

update trigger is chufale 。。。。。

update trigger is chufale 。。。。。

update trigger is chufale 。。。。。

已更新8行;

:new 與: old:必須是針對行級觸發器的,也就是說要使用這兩個變數的觸發器一定有for each row

這兩個變數是系統自動提供的陣列變數,:new用來記錄新插入的值,old用來記錄被刪除的值;

使用insert的時候只有:new裡有值;

使用delete的時候只有:old裡有值;

使用update的時候:new和:old裡都有值;

可以這樣使用: dbms_output。put_line(‘insert trigger is chufa

dbms_output。put_line(’new id is : ‘||:new。stui

dbms_output。put_line(’new name is : ‘||:new。st

dbms_output。put_line(’new se is : ‘||:new。se);

可以這樣從資料字典中檢視一個表上有哪幾個觸發器:

SQL> select trigger_name from user_triggers

2 where table_name=upper(’student‘);

TRIGGER_NAME

————————————————

TG_INSERT

TG_UPDATESTUDENT

帶有:old變數的行級delete觸發器:

create or replace trigger tg_deletestudent

before delete on student

for each row

begin

dbms_output。put_line(’old is: ‘||:old。stuid);

dbms_output。put_line(’old name: ‘||:old。stuname);

end;

/

執行效果:

SQL> delete from student;

old is: 202

old name: dongqian

old is: 101

old name: liudehua

old is: 102

old name: lingqingxia

old is: 103

old name: lichanggong

old is: 104

old name: zhenxiuwen

old is: 1001

old name: lilianjie

old is: 1009

old name: tongleifuck

old is: 203

old name: kfdj

old is: 209

old name: fuck

已刪除9行

When的使用:如果在begin也就是說觸發器的PL/SQL主體塊執行前加上when(old。se=’f’)的話,DML操作照做不誤,但是隻會在刪除

Se=’f’的那行的時候才會執行觸發器的主體動作,執行效果:

SQL> delete from student;

old is: 209

old name: fuck

已刪除9行; 這裡雖然刪了9行,但是隻執行了一次觸發器的主體,做為一個行級觸發器;

混合型別觸發器:

Inserting,deleting,updating三個謂詞可以分別指示當前操作到底是哪個;

create or replace trigger hunhetrigger

before insert or update or delete on student

for each row

begin

if inserting then

dbms_output。put_line(’insert le……。。。‘);

end if;

if deleting then

dbms_output。put_line(’delete le ……。‘);

end if;

end;

/

插入的時候就自動判斷當前動作為插入:

SQL> insert into student values(303,’me‘,’f‘);

insert le……。。。

刪除的時候就自動判斷當前動作為刪除:

SQL> delete from student;

delete le ……。

注意,既然觸發器內部的主體PL/SQL是語句,那麼它同樣也可以是插入刪除操作而不一定只是dbms_output列印一些資訊;

這正是日誌表的原理:在使用者執行了DML語句的時候觸發主體為插入日誌表以記錄操作軌跡的觸發器;

為什麼用觸發器? 當我們有兩個表用來記錄商品的出庫入庫情況,good_store用來記錄庫存的產品類別和數量,

而good_out用來記錄出庫的產品類別和數量,那麼每當我們出庫的某個類別的產品一定數量的時候,我們應該在good_out中插入該產品的類別和

出庫數量,而同時也應該在good_store表中用update來更新庫存的相應類別的產品的數量;這就交給了我們兩個必須完成的任務:插入good_out

表後更新good_store表,這樣的手工過程使得我們覺得非常ugly,如果只做其中一個那造成資料的不一致;所以現在我們可以用觸發器,在

Good_out表的插入操作上繫結一個對good_store進行更新的觸發器;當然這個過程應該是一個事務,你不必擔心插入good_out表執行了,而繫結在這個動作上的觸發器操作不會執行,相信Oracle設計為原子性了;

注意:觸發器會使得原來的SQL語句速度變慢;

替代觸發器:

建立在檢視上的觸發器,就是替代觸發器,只能是行級觸發器;

為什麼要用替代觸發器?

假如你有一個檢視是基於多個表的欄位連線查詢得到的;現在如果你想直接對著這個檢視insert;那你一定在想,我對檢視的插入操作

怎麼來反應到組成這個檢視的各個表中呢?事實上,除了定義一個觸發器來繫結在對檢視上的插入動作上外,你沒有別的辦法透過系統的報錯而直接向檢視中插入資料;這就是我們用替代觸發器的原因;替換的意思實際上是觸發器的主體部分把對檢視的插入操作轉換成詳細的對各個表的插入;

變異表:變異表就是當前SQL語句正在修改的表,所以在一個變異表上繫結的觸發器不可以使用cout()函式,原因很簡單:SQL語句剛剛修改了表,你怎麼統計??

約束表:

維護:

Alter trigger …。。disenable; 使得觸發器不可用;

Alter trigger ……enable; 開啟觸發器;

Oracle的內建程式包

擴充套件資料庫的功能;

為PL/SQL提供對SQL功能的訪問;

一般具有sys許可權的高階管理人員使用;

一個典型的程式包就是dbms_output,你老是用它的過程put_line();

Dbms_standard 提供語言工具;

Dbms_lob操作Oracle LOB;就是針對大型資料的操作設計的;

Dbms_lock使用者定義的鎖;

Dbms_job 允許對PL/SQL過程進行排程;

Dbms_alert 支援資料庫事件的非同步通知;

1,dbms_output的一些過程:

a):enable

b):disable

c):put只是把資料放到快取(SQL-Plus的快取,實際就是整個視窗)中,無輸出功能;

d):put_line可以使得以前放在快取中所有資料輸出;並且換到下一行;

e):new_line

f):get_line

g):get_lines

2,dmbs_lob ,這個包只能是由系統管理員來操作;

Clob以字元資料儲存可達2G;

Blob以二進位制資料儲存可達4G;

Nclob以unicode字元儲存;

一個檔案下載列表的例子:

建立下載目錄表:

create table downfilelist

id varchar(20) not null primary key,

name varchar(40) not null,

filelocation bfile,

description clob

/

建立目錄:

create or replace directory filedir as ’f:\oracle‘

/只是向Oralce註冊了目錄,實際上並不會真的建立目錄在磁碟上;Oracle無權管理和鎖定作業系統的檔案系統;

向目錄表中插入資料:

insert into downfilelist

values(’10001‘,’oracle plsal程式設計指南‘,bfilename(upper(’filedir‘),’demo。mp3‘),’this is a mp3 music‘)

insert into downfilelist

values(’10002‘,’java 大權‘, bfilename(upper(’filedir‘),’x。jpg‘),’good super girl‘)

/在filedir的目錄f:\oracle下實際儲存著demo。mp3 ,x。jpg;

注意,如果你試圖查詢,效果是 :

sys>select * from downfilelist;

SP2-0678: 列或屬性型別無法透過 SQL*Plus 顯示

因為第三列是無法顯示的,是一個二進位制的;

下面使用dbms_lob的一些過程來進行操作:

1,read過程

declare

tempdesc clob;

ireadcount int;

istart int;

soutputdesc varchar(100);

begin

ireadcount:=5;

istart:=1;

select description into tempdesc from downfilelist where id=’10001‘;

dbms_lob。read(tempdesc,ireadcount,istart,soutputdesc); 把clob型別的tempdesc中的資料讀到字元型別的soutputdesc裡;

dbms_output。put_line(’Top 5 character is: ‘||soutputdesc);

end;

/注意,對unicode來說,漢字和字母所佔的位數是一樣的;

2,getlength函式

select description into tempclob from downfilelist where id=‘10001’;

ilen:=dbms_lob。GetLength(tempclob);

append,copy……。。

發現這樣的現象:select x into y的時候,y並不是獨立於x的複製,因為當修改y的時候x也被修改了;

3, fileexists函式

select id ,dbms_lob。fileexists(filelocation) from downfilelist;

如果在bfile型別欄位filelocation指定的系統下的目錄中存在filelocation指定的系統檔案,則返回int 1,否則返回0;

這說明Oracle還是可以檢測到系統的檔案情況的,如同java。io包裡的類一樣;

對bfile型別資料的操作函式有fileisopen,fileopen,fileclose等等;