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

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

oracle 触发器的种类和触发事件

發(fā)布時(shí)間:2024/8/26 编程问答 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 oracle 触发器的种类和触发事件 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
觸發(fā)器的種類和觸發(fā)事件 ?
觸發(fā)器必須由事件才能觸發(fā)。觸發(fā)器的觸發(fā)事件分可為3類,分別是DML事件、DDL事件和數(shù)據(jù)庫(kù)事件。?
每類事件包含若干個(gè)事件,如下所示。數(shù)據(jù)庫(kù)的事件是具體的,在創(chuàng)建觸發(fā)器時(shí)要指明觸發(fā)的事件。?
種? 類 關(guān) 鍵 字 含??? 義?
Sql代碼??
  • DML事件(3種)???INSERT??在表或視圖中插入數(shù)據(jù)時(shí)觸發(fā)??
  • ????UPDATE??修改表或視圖中的數(shù)據(jù)時(shí)觸發(fā)??
  • ????DELETE??在刪除表或視圖中的數(shù)據(jù)時(shí)觸發(fā)??
  • DDL事件(3種)???CREATE??在創(chuàng)建新對(duì)象時(shí)觸發(fā)??
  • ????ALTER???修改數(shù)據(jù)庫(kù)或數(shù)據(jù)庫(kù)對(duì)象時(shí)觸發(fā)??
  • ????DROP????刪除對(duì)象時(shí)觸發(fā)??
  • 數(shù)據(jù)庫(kù)事件(5種)???STARTUP?數(shù)據(jù)打開(kāi)時(shí)觸發(fā)??
  • ????SHUTDOWN????在使用NORMAL或IMMEDIATE選項(xiàng)關(guān)閉數(shù)據(jù)庫(kù)時(shí)觸發(fā)??
  • ????LOGON???當(dāng)用戶連接到數(shù)據(jù)庫(kù)并建立會(huì)話時(shí)觸發(fā)??
  • ????LOGOFF??當(dāng)一個(gè)會(huì)話從數(shù)據(jù)庫(kù)中斷開(kāi)時(shí)觸發(fā)??
  • ????SERVERERROR?發(fā)生服務(wù)器錯(cuò)誤時(shí)觸發(fā)??

  • 觸發(fā)器的類型可劃分為4種:數(shù)據(jù)操縱語(yǔ)言(DML)觸發(fā)器、替代(INSTEAD OF)觸發(fā)器、數(shù)據(jù)定義語(yǔ)言(DDL)觸發(fā)器和數(shù)據(jù)庫(kù)事件觸發(fā)器。?
    各類觸發(fā)器的作用如下所示。?
    Sql代碼??
  • 種??類????簡(jiǎn)??稱????作????用??
  • 數(shù)據(jù)操縱語(yǔ)言觸發(fā)器???DML觸發(fā)器??創(chuàng)建在表上,由DML事件引發(fā)的觸發(fā)器??
  • 替代觸發(fā)器???INSTEAD?OF觸發(fā)器???創(chuàng)建在視圖上,用來(lái)替換對(duì)視圖進(jìn)行的插入、刪除和修改操作??
  • 數(shù)據(jù)定義語(yǔ)言觸發(fā)器???DDL觸發(fā)器??定義在模式上,觸發(fā)事件是數(shù)據(jù)庫(kù)對(duì)象的創(chuàng)建和修改??
  • 數(shù)據(jù)庫(kù)事件觸發(fā)器????—???定義在整個(gè)數(shù)據(jù)庫(kù)或模式上,觸發(fā)事件是數(shù)據(jù)庫(kù)事件??

  • DML觸發(fā)器的要點(diǎn) ?
    DML觸發(fā)器是定義在表上的觸發(fā)器,由DML事件引發(fā)。編寫(xiě)DML觸發(fā)器的要素是:?
    * 確定觸發(fā)的表,即在其上定義觸發(fā)器的表。?
    * 確定觸發(fā)的事件,DML觸發(fā)器的觸發(fā)事件有INSERT、UPDATE和DELETE三種,說(shuō)明見(jiàn)下。?
    * 確定觸發(fā)時(shí)間。觸發(fā)的時(shí)間有BEFORE和AFTER兩種,分別表示觸發(fā)動(dòng)作發(fā)生在DML語(yǔ)句執(zhí)行之前和語(yǔ)句執(zhí)行之后。?
    * 確定觸發(fā)級(jí)別,有語(yǔ)句級(jí)觸發(fā)器和行級(jí)觸發(fā)器兩種。語(yǔ)句級(jí)觸發(fā)器表示SQL語(yǔ)句只觸發(fā)一次觸發(fā)器,行級(jí)觸發(fā)器表示SQL語(yǔ)句影響的每一行都要觸發(fā)一次。?
    由于在同一個(gè)表上可以定義多個(gè)DML觸發(fā)器,因此觸發(fā)器本身和引發(fā)觸發(fā)器的SQL語(yǔ)句在執(zhí)行的順序上有先后的關(guān)系。它們的順序是:?
    * 如果存在語(yǔ)句級(jí)BEFORE觸發(fā)器,則先執(zhí)行一次語(yǔ)句級(jí)BEFORE觸發(fā)器。?
    * 在SQL語(yǔ)句的執(zhí)行過(guò)程中,如果存在行級(jí)BEFORE觸發(fā)器,則SQL語(yǔ)句在對(duì)每一行操作之前,都要先執(zhí)行一次行級(jí)BEFORE觸發(fā)器,然后才對(duì)行進(jìn)行操作。如果存在行級(jí)AFTER觸發(fā)器,則SQL語(yǔ)句在對(duì)每一行操作之后,都要再執(zhí)行一次行級(jí)AFTER觸發(fā)器。?
    * 如果存在語(yǔ)句級(jí)AFTER觸發(fā)器,則在SQL語(yǔ)句執(zhí)行完畢后,要最后執(zhí)行一次語(yǔ)句級(jí)AFTER觸發(fā)器。?
    DML觸發(fā)器還有一些具體的問(wèn)題,說(shuō)明如下:?
    * 如果有多個(gè)觸發(fā)器被定義成為相同時(shí)間、相同事件觸發(fā),且最后定義的觸發(fā)器是有效的,則最后定義的觸發(fā)器被觸發(fā),其他觸發(fā)器不執(zhí)行。?
    * 一個(gè)觸發(fā)器可由多個(gè)不同的DML操作觸發(fā)。在觸發(fā)器中,可用INSERTING、DELETING、UPDATING謂詞來(lái)區(qū)別不同的DML操作。這些謂詞可以在IF分支條件語(yǔ)句中作為判斷條件來(lái)使用。?
    * 在行級(jí)觸發(fā)器中,用:new 和:old(稱為偽記錄)來(lái)訪問(wèn)數(shù)據(jù)變更前后的值。但要注意,INSERT語(yǔ)句插入一條新記錄,所以沒(méi)有:old記錄,而DELETE語(yǔ)句刪除掉一條已經(jīng)存在的記錄,所以沒(méi)有:new記錄。UPDATE語(yǔ)句既有:old記錄,也有:new記錄,分別代表修改前后的記錄。引用具體的某一列的值的方法是:?
    ??????? ld.字段名或:new.字段名?
    * 觸發(fā)器體內(nèi)禁止使用COMMIT、ROLLBACK、SAVEPOINT語(yǔ)句,也禁止直接或間接地調(diào)用含有上述語(yǔ)句的存儲(chǔ)過(guò)程。?
    定義一個(gè)觸發(fā)器時(shí)要考慮上述多種情況,并根據(jù)具體的需要來(lái)決定觸發(fā)器的種類。?
    DML觸發(fā)器的創(chuàng)建 ?
    創(chuàng)建DML觸發(fā)器需要CREATE TRIGGER系統(tǒng)權(quán)限。創(chuàng)建DML觸發(fā)器的語(yǔ)法如下:?
    CREATE [OR REPLACE] TRIGGER 觸發(fā)器名?
    {BEFORE|AFTER|INSTEAD OF} 觸發(fā)事件1 [OR 觸發(fā)事件2...]?
    ON 表名?
    WHEN 觸發(fā)條件?
    [FOR EACH ROW]?
    DECLARE?
    聲明部分?
    BEGIN?
    主體部分?
    END;?
    其中:?
    OR REPLACE:表示如果存在同名觸發(fā)器,則覆蓋原有同名觸發(fā)器。?
    BEFORE、AFTER和INSTEAD OF:說(shuō)明觸發(fā)器的類型。?
    WHEN 觸發(fā)條件:表示當(dāng)該條件滿足時(shí),觸發(fā)器才能執(zhí)行。?
    觸發(fā)事件:指INSERT、DELETE或UPDATE事件,事件可以并行出現(xiàn),中間用OR連接。?
    對(duì)于UPDATE事件,還可以用以下形式表示對(duì)某些列的修改會(huì)引起觸發(fā)器的動(dòng)作:?
    UPDATE OF 列名1,列名2...?
    ON 表名:表示為哪一個(gè)表創(chuàng)建觸發(fā)器。?
    FOR EACH ROW:表示觸發(fā)器為行級(jí)觸發(fā)器,省略則為語(yǔ)句級(jí)觸發(fā)器。?
    觸發(fā)器的創(chuàng)建者或具有DROP ANY TIRGGER系統(tǒng)權(quán)限的人才能刪除觸發(fā)器。刪除觸發(fā)器的語(yǔ)法如下:?
    DROP TIRGGER 觸發(fā)器名?
    可以通過(guò)命令設(shè)置觸發(fā)器的可用狀態(tài),使其暫時(shí)關(guān)閉或重新打開(kāi),即當(dāng)觸發(fā)器暫時(shí)不用時(shí),可以將其置成無(wú)效狀態(tài),在使用時(shí)重新打開(kāi)。該命令語(yǔ)法如下:?
    ALTER TRIGGER 觸發(fā)器名 {DISABLE|ENABLE}?
    其中,DISABLE表示使觸發(fā)器失效,ENABLE表示使觸發(fā)器生效。?
    同存儲(chǔ)過(guò)程類似,觸發(fā)器可以用SHOW ERRORS 檢查編譯錯(cuò)誤。?
    行級(jí)觸發(fā)器的應(yīng)用 ?
    在行級(jí)觸發(fā)器中,SQL語(yǔ)句影響的每一行都會(huì)觸發(fā)一次觸發(fā)器,所以行級(jí)觸發(fā)器往往用在對(duì)表的每一行的操作進(jìn)行控制的場(chǎng)合。若在觸發(fā)器定義中出現(xiàn)FOR EACH ROW子句,則為語(yǔ)句級(jí)觸發(fā)器。?
    【訓(xùn)練1】? 創(chuàng)建包含插入、刪除、修改多種觸發(fā)事件的觸發(fā)器DML_LOG,對(duì)EMP表的操作進(jìn)行記錄。用INSERTING、DELETING、UPDATING謂詞來(lái)區(qū)別不同的DML操作。?
    在創(chuàng)建觸發(fā)器之前,需要先創(chuàng)建事件記錄表LOGS,該表用來(lái)對(duì)操作進(jìn)行記錄。該表的字段含義解釋如下:?
    LOG_ID:操作記錄的編號(hào),數(shù)值型,它是該表的主鍵,由序列自動(dòng)生成。?
    LOG_TABLE:進(jìn)行操作的表名,字符型,非空,該表設(shè)計(jì)成可以由多個(gè)觸發(fā)器共享使用。比如我們可以為dept表創(chuàng)建類似的觸發(fā)器,同樣將操作記錄到該表。?
    LOG_DML:操作的動(dòng)作,即INSERT、DELETE或UPDATE三種之一。?
    LOG_KEY_ID:操作時(shí)表的主鍵值,數(shù)值型。之所以記錄表的主鍵,是因?yàn)橹麈I是表的記錄的惟一標(biāo)識(shí),可以識(shí)別是對(duì)哪一條記錄進(jìn)行了操作。對(duì)于emp表,主鍵是empno。?
    LOG_DATE:操作的日期,日期型,取當(dāng)前的系統(tǒng)時(shí)間。?
    LOG_USER:操作者,字符型,取當(dāng)時(shí)的操作者賬戶名。比如登錄SCOTT賬戶進(jìn)行操作,在該字段中,記錄賬戶名為SCOTT。?
    步驟1:在SQL*Plus中登錄STUDENT賬戶,創(chuàng)建如下的記錄表LOGS:?
    Sql代碼??
  • CREATE?TABLE?logs(??
  • ????????LOG_ID?NUMBER(10)?PRIMARY?KEY,??
  • ????????LOG_TABLE?VARCHAR2(10)?NOT?NULL,??
  • ????????LOG_DML?VARCHAR2(10),??
  • ????????LOG_KEY_ID?NUMBER(10),??
  • ????????LOG_DATE?DATE,??
  • ????????LOG_USER?VARCHAR2(15)??
  • ????????);??

  • 執(zhí)行結(jié)果:?
    Sql代碼??
  • 表已創(chuàng)建。??

  • 步驟2:創(chuàng)建一個(gè)LOGS表的主鍵序列LOGS_ID_SEQ:?
    Sql代碼??
  • CREATE?SEQUENCE?logs_id_squ?INCREMENT?BY?1???
  • ????????START?WITH?1?MAXVALUE?9999999?NOCYCLE?NOCACHE;??

  • 執(zhí)行結(jié)果:?
    Sql代碼??
  • 序列已創(chuàng)建。??

  • 步驟3:創(chuàng)建和編譯以下觸發(fā)器:?
    Sql代碼??
  • CREATE?OR?REPLACE?TRIGGER?DML_LOG??
  • ????????BEFORE?--觸發(fā)時(shí)間為操作前??
  • ????????DELETE?OR?INSERT?OR?UPDATE?--?由三種事件觸發(fā)??
  • ????????ON?emp??
  • ????????FOR?EACH?ROW?--?行級(jí)觸發(fā)器??
  • ????????BEGIN??
  • IF?INSERTING?THEN???
  • ????????INSERT?INTO?logs????????VALUES(logs_id_squ.NEXTVAL,'EMP','INSERT',:new.empno,SYSDATE,USER);??
  • ?????????ELSIF?DELETING?THEN??
  • ?????????INSERT?INTO?logs???????VALUES(logs_id_squ.NEXTVAL,'EMP','DELETE',:old.empno,SYSDATE,USER);??
  • ?????????ELSE??
  • ?????????????INSERT?INTO?logs???????VALUES(logs_id_squ.NEXTVAL,'EMP','UPDATE',:new.empno,SYSDATE,USER);??
  • ????????END?IF;??
  • ????????END;??

  • 執(zhí)行結(jié)果:?
    觸發(fā)器已創(chuàng)建?
    步驟4:在EMP表中插入記錄:?
    Sql代碼??
  • INSERT?INTO?emp(empno,ename,job,sal)?VALUES(8001,'MARY','CLERK',1000);??
  • ????????COMMIT;??

  • 執(zhí)行結(jié)果:?
    Sql代碼??
  • 已創(chuàng)建1行。??
  • ????????提交完成。??

  • 步驟5:檢查L(zhǎng)OGS表中記錄的信息:?
    Sql代碼??
  • SELECT?*?FROM?LOGS;??

  • 執(zhí)行結(jié)果為:?
    ??? Sql代碼??
  • LOG_ID?LOG_TABLE??LOG_DML????LOG_KEY_ID?LOG_DATE???LOG_USER??
  • ????????-----------------?-----------------?------------------?-----------------------?----------------?-------------------??
  • ??????????1?EMP?????????INSERT????????????8001????29-3月?-04?????STUDENT??
  • ????????已選擇?1?行。??

  • 說(shuō)明:本例中在emp表上創(chuàng)建了一個(gè)由INSERT或DELETE或UPDATE事件觸發(fā)的行級(jí)觸發(fā)器,觸發(fā)器的名稱是LOG_EMP。對(duì)于不同的操作,記錄的內(nèi)容不同。本例中只插入了一條記錄,如果用一條不帶WHERE條件的UPDATE語(yǔ)句來(lái)修改所有雇員的工資,則將逐行觸發(fā)觸發(fā)器。?
    INSERT、DELETE和UPDATE都能引發(fā)觸發(fā)器動(dòng)作,在分支語(yǔ)句中使用INSERTING、DELETING和UPDATING來(lái)區(qū)別是由哪種操作引發(fā)的觸發(fā)器動(dòng)作。?
    在本例的插入動(dòng)作中,LOG_ID字段由序列LOG_ID_SQU自動(dòng)填充為1;LOGS表LOG_KEY_ID字段記錄的是新插入記錄的主鍵8001;LOD_DML字段記錄的是插入動(dòng)作INSERT;LOG_TABLE字段記錄當(dāng)前表名EMP;LOG_DATE字段記錄插入的時(shí)間04年3月1日;LOG_USER字段記錄插入者STUDENT。?
    【練習(xí)1】修改、刪除剛剛插入的雇員記錄,提交后檢查L(zhǎng)OGS表的結(jié)果。?
    【練習(xí)2】為DEPT表創(chuàng)建同樣的觸發(fā)器,使用LOGS表進(jìn)行記錄,并檢驗(yàn)結(jié)果。?
    【訓(xùn)練2】? 創(chuàng)建一個(gè)行級(jí)觸發(fā)器LOG_SAL,記錄對(duì)職務(wù)為CLERK的雇員工資的修改,且當(dāng)修改幅度超過(guò)200時(shí)才進(jìn)行記錄。用WHEN條件限定觸發(fā)器。?
    在創(chuàng)建觸發(fā)器之前,需要先創(chuàng)建事件記錄表LOGERR,該表用來(lái)對(duì)操作進(jìn)行記錄。該表的字段含義解釋如下:?
    NUM:數(shù)值型,用于記錄序號(hào)。?
    MESSAGE:字符型,用于記錄錯(cuò)誤信息。?
    步驟1:在SQL*Plus中登錄STUDENT賬戶,創(chuàng)建如下的記錄表LOGERR:?
    Sql代碼??
  • CREATE?TABLE?logerr(??
  • ????????NUM?NUMBER(10)?NOT?NULL,??
  • ????????MESSAGE?VARCHAR2(50)?NOT?NULL??
  • ????????);??

  • 執(zhí)行結(jié)果:?
    Sql代碼??
  • 表已創(chuàng)建。??

  • 步驟2:創(chuàng)建和編譯以下觸發(fā)器:?
    Sql代碼??
  • CREATE?OR?REPLACE?TRIGGER?log_sal??
  • ????????BEFORE??
  • ????????UPDATE?OF?sal??
  • ????????ON?emp??
  • ????????FOR?EACH?ROW??
  • ????????WHEN?(new.job='CLERK'?AND?(ABS(new.sal-old.sal)>200))???
  • DECLARE???
  • ????????v_no?NUMBER;??
  • ????????BEGIN??
  • ????????SELECT?COUNT(*)?INTO?v_no?FROM?logerr;???
  • ????????INSERT?INTO?logerr?VALUES(v_no+1,'雇員'||:new.ename||'的原工資:'||:old.sal||'新工資:'||:new.sal);??
  • ????????END;??

  • 執(zhí)行結(jié)果:?
    Sql代碼??
  • 觸發(fā)器已創(chuàng)建。??

  • 步驟3:在EMP表中更新記錄:?
    Sql代碼??
  • UPDATE?emp?SET?sal=sal+550?WHERE?empno=7788;??
  • ????????UPDATE?emp?SET?sal=sal+500?WHERE?empno=7369;??
  • ????????UPDATE?emp?SET?sal=sal+50?WHERE?empno=7876;??
  • ????????COMMIT;??

  • 執(zhí)行結(jié)果:?
    Sql代碼??
  • 已更新?1?行。??
  • ????????已更新?1?行。??
  • ????????已更新?1?行。??
  • ????????提交完成。??

  • 步驟4:檢查L(zhǎng)OGSAL表中記錄的信息:?
    Sql代碼??
  • SELECT?*?FROM?logerr;??

  • 執(zhí)行結(jié)果為:
    ?????? Sql代碼??
  • NUM?MESSAGE??
  • ------------------?--------------------------------------------------------??
  • ?????????????1?雇員SMITH的原工資:800新工資:1300??
  • ????????已選擇?1?行。??

  • ? 說(shuō)明:本例中,在emp表的sal列上創(chuàng)建了一個(gè)由UPDATE事件觸發(fā)的行級(jí)觸發(fā)器,觸發(fā)器的名稱是LOG_SAL。該觸發(fā)器由WHEN語(yǔ)句限定,只有當(dāng)被修改工資的雇員職務(wù)為CLERK,且修改的工資超過(guò)200時(shí)才進(jìn)行觸發(fā),否則不進(jìn)行觸發(fā)。?
    所以在驗(yàn)證過(guò)程中,雖然修改了3條記錄,但通過(guò)查詢語(yǔ)句發(fā)現(xiàn):第一條修改語(yǔ)句修改編號(hào)為7788的SCOTT記錄,因?yàn)镾COTT的職務(wù)是ANALYST,不符合WHEN條件,沒(méi)有引起觸發(fā)器動(dòng)作;第二條修改語(yǔ)句修改編號(hào)為7369的SMITH的記錄,職務(wù)為CLERK,因?yàn)樵黾拥墓べY(500)超過(guò)了200,所以引起觸發(fā)器動(dòng)作,并在LOGERR表中進(jìn)行了記錄;第三條修改語(yǔ)句修改編號(hào)為7876的雇員ADAMS的記錄,雖然ADAMS的職務(wù)為CLERK,但修改的工資(50)沒(méi)有超過(guò)200,所以沒(méi)有引起觸發(fā)器動(dòng)作。?
    注意:在WHEN條件中引用new和old不需要在前面加“: ”。?
    在以上實(shí)例中,記錄了對(duì)工資的修改超出范圍的信息,但沒(méi)有限制對(duì)工資的修改。那么當(dāng)對(duì)雇員工資的修改幅度不滿足條件時(shí),能否直接限制對(duì)工資的修改呢?答案是肯定的。?
    【訓(xùn)練3】? 創(chuàng)建觸發(fā)器CHECK_SAL,當(dāng)對(duì)職務(wù)為CLERK的雇員的工資修改超出500至2000的范圍時(shí),進(jìn)行限制。?
    步驟1:創(chuàng)建和編譯以下觸發(fā)器:?
    Sql代碼??
  • CREATE?OR?REPLACE?TRIGGER?CHECK_SAL??
  • ????????BEFORE??
  • ????????UPDATE??
  • ????????ON?emp??
  • ????????FOR?EACH?ROW??
  • ????????BEGIN??
  • IF?:new.job='CLERK'?AND?(:new.sal<500?OR?:new.sal>2000)?THEN??
  • ?????????RAISE_APPLICATION_ERROR(-20001,?'工資修改超出范圍,操作取消!');??
  • ????????END?IF;??
  • ????????END;??

  • 執(zhí)行結(jié)果:?
    Sql代碼??
  • 觸發(fā)器已創(chuàng)建。??

  • 步驟2:在EMP表中插入記錄:?
    Sql代碼??
  • UPDATE?emp?SET?sal=800?WHERE?empno=7876;??
  • ????????UPDATE?emp?SET?sal=450?WHERE?empno=7876;??
  • ????????COMMIT;??

  • 執(zhí)行結(jié)果:?
    Sql代碼??
  • UPDATE?emp?SET?sal=450?WHERE?empno=7876??
  • ????????????????*??
  • ????????ERROR?位于第?1?行:??
  • ????????ORA-20001:?工資修改超出范圍,操作取消!??
  • ????????ORA-06512:?在"STUDENT.CHECK_SAL",?line?3??
  • ????????ORA-04088:?觸發(fā)器?'STUDENT.CHECK_SAL'?執(zhí)行過(guò)程中出錯(cuò)提交完成。??

  • 步驟3:檢查工資的修改結(jié)果:?
    Sql代碼??
  • SELECT?empno,ename,job,sal?FROM?emp?WHERE?empno=7876;??

  • 執(zhí)行結(jié)果為:?
    ??? Sql代碼??
  • EMPNO?ENAME??????JOB??????????????SAL??
  • -----------------?-------------?-------------?------------------------??
  • ????????7876??ADAMS??????CLERK????????????800??

  • 說(shuō)明:在觸發(fā)器中,當(dāng)IF語(yǔ)句的條件滿足時(shí),即對(duì)職務(wù)為CLERK的雇員工資的修改超出指定范圍時(shí),用RAISE_APPLICATION_ERROR語(yǔ)句來(lái)定義一個(gè)臨時(shí)定義的異常,并立即引發(fā)異常。由于觸發(fā)器是BEFORE類型,因此觸發(fā)器先執(zhí)行,觸發(fā)器因異常而終止,SQL語(yǔ)句的執(zhí)行就會(huì)取消。?
    通過(guò)步驟2的執(zhí)行信息可以看到,第一條語(yǔ)句修改編號(hào)為7876的雇員ADAMS的工資為800,成功執(zhí)行。第二條語(yǔ)句修改雇員ADAMS的工資為450,發(fā)生異常,執(zhí)行失敗。這樣就阻止了不符合條件的工資的修改。通過(guò)步驟3的查詢可以看到,雇員ADAMS最后的工資是800,即發(fā)生異常之前的修改結(jié)果。?
    【練習(xí)3】限定對(duì)emp表的修改,只能修改部門(mén)10的雇員工資。?
    ?? 【訓(xùn)練4】? 創(chuàng)建一個(gè)行級(jí)觸發(fā)器CASCADE_UPDATE,當(dāng)修改部門(mén)編號(hào)時(shí),EMP表的相關(guān)行的部門(mén)編號(hào)也自動(dòng)修改。該觸發(fā)器稱為級(jí)聯(lián)修改觸發(fā)器。?
    步驟1:創(chuàng)建和編譯以下觸發(fā)器:?
    Sql代碼??
  • CREATE?TRIGGER?CASCADE_UPDATE??
  • AFTER???
  • UPDATE?OF?deptno??
  • ON?DEPT??
  • FOR?EACH?ROW??
  • BEGIN??
  • UPDATEEMP?SET?EMP.DEPTNO=:NEW.DEPTNO??
  • ?????????WHERE?EMP.DEPTNO=:OLD.DEPTNO;??
  • ????????END;??

  • 執(zhí)行結(jié)果:?
    Sql代碼??
  • 觸發(fā)器已創(chuàng)建??

  • 步驟2:驗(yàn)證觸發(fā)器:?
    Sql代碼??
  • UPDATE?dept?SET?deptno=11?WHERE?deptno=10;??
  • ????????COMMIT;??

  • 執(zhí)行結(jié)果:?
    Sql代碼??
  • 已更新?1?行。???

  • 執(zhí)行查詢:?
    Sql代碼??
  • SELECT?empno,ename,deptno?FROM?emp;??

  • 執(zhí)行結(jié)果:?
    ?? Sql代碼??
  • ?EMPNO?ENAME??????????DEPTNO??
  • ????-----------------?-----------?-------------------------??
  • ?????????7369?SMITH?????????????????20??
  • ?????????7499?ALLEN?????????????????30??
  • ????????7521?WARD???????????????????30??
  • ????????7566?JONES??????????????????20??
  • 7654?MARTIN?????????????????30??
  • ????????7698?BLAKE??????????????????30??
  • ?????????7782?CLARK?????????????????11??
  • ?????????7839?KING??????????????????11??
  • ????????7844?TURNER?????????????????30??
  • ????????7876?ADAMS??????????????????20??
  • ????????7900?JAMES??????????????????30??
  • ?????????7902?FORD??????????????????20??
  • ?????????7934?MILLER????????????????11??
  • ????????7788?SCOTT??????????????????20??

  • 說(shuō)明:通過(guò)檢查雇員的部門(mén)編號(hào),發(fā)現(xiàn)原來(lái)編號(hào)為10的部門(mén)編號(hào)被修改為11。?
    本例中的UPDATE OF deptno表示只有在修改表的DEPTNO列時(shí)才引發(fā)觸發(fā)器,對(duì)其他列的修改不會(huì)引起觸發(fā)器的動(dòng)作。在觸發(fā)器中,對(duì)雇員表的部門(mén)編號(hào)與修改之前的部門(mén)編號(hào)一樣的雇員,修改其部門(mén)編號(hào)為新的部門(mén)編號(hào)。注意,在語(yǔ)句中同時(shí)用到了:new和:old來(lái)引用修改部門(mén)編號(hào)前后的部門(mén)編號(hào)。?
    【練習(xí)4】建立級(jí)聯(lián)刪除觸發(fā)器CASCADE_DELETE,當(dāng)刪除部門(mén)時(shí),級(jí)聯(lián)刪除EMP表的雇員記錄。?
    利用觸發(fā)器還可以修改數(shù)據(jù)。?
    【訓(xùn)練5】? 將插入的雇員的名字變成以大寫(xiě)字母開(kāi)頭。?
    步驟1:創(chuàng)建和編譯以下觸發(fā)器:?
    Sql代碼??
  • CREATE?OR?REPLACE?TRIGGER?INITCAP??
  • BEFORE?INSERT???
  • ON?EMP??
  • FOR?EACH?ROW??
  • BEGIN??
  • ?:new.ename:=INITCAP(:new.ename);??
  • END;??

  • 執(zhí)行結(jié)果:?
    Sql代碼??
  • 觸發(fā)器已創(chuàng)建。??

  • 步驟2:驗(yàn)證運(yùn)行結(jié)果:?
    Sql代碼??
  • INSERT?INTO?emp(empno,ename,job,sal)?VALUES(1000,'BILL','CLERK',1500);??

  • 執(zhí)行結(jié)果:?
    Sql代碼??
  • 已創(chuàng)建?1?行。??

  • 執(zhí)行查詢:?
    Sql代碼??
  • SELECT?ename,job,sal?FROM?emp?WHERE?empno=1000;??

  • 執(zhí)行結(jié)果:?
    Sql代碼??
  • ENAME??????JOB??????????????SAL??
  • ????????-------------?-------------?------------------------??
  • ????????Bill??????????CLERK???????????1500??

  • 說(shuō)明:在本例中,通過(guò)直接為:new.ename進(jìn)行賦值,修改了插入的值,但是這種用法只能在BEFORE型觸發(fā)器中使用。驗(yàn)證結(jié)果為,在插入語(yǔ)句中雇員名稱為大寫(xiě)的BILL,查詢結(jié)果中雇員名稱已經(jīng)轉(zhuǎn)換成以大寫(xiě)開(kāi)頭的Bill。?
    【練習(xí)5】限定一次對(duì)雇員的工資修改不超過(guò)原工資的10%。?
    語(yǔ)句級(jí)觸發(fā)器的應(yīng)用 ?
    同行級(jí)觸發(fā)器不同,語(yǔ)句級(jí)觸發(fā)器的每個(gè)操作語(yǔ)句不管操作的行數(shù)是多少,只觸發(fā)一次觸發(fā)器,所以語(yǔ)句級(jí)觸發(fā)器適合于對(duì)整個(gè)表的操作權(quán)限等進(jìn)行控制。在觸發(fā)器定義中若省略FOR EACH ROW子句,則為語(yǔ)句級(jí)觸發(fā)器。?
    【訓(xùn)練1】? 創(chuàng)建一個(gè)語(yǔ)句級(jí)觸發(fā)器CHECK_TIME,限定對(duì)表EMP的修改時(shí)間為周一至周五的早8點(diǎn)至晚5點(diǎn)。?
    步驟1:創(chuàng)建和編譯以下觸發(fā)器:?
    Sql代碼??
  • CREATE?OR?REPLACE?TRIGGER?CHECK_TIME??
  • BEFORE??
  • UPDATE?OR?INSERT?OR?DELETE???
  • ON?EMP??
  • BEGIN??
  • ?IF?(TO_CHAR(SYSDATE,'DY')?IN?('SAT','SUN'))???
  • ?OR?TO_CHAR(SYSDATE,'HH24')<?'08'???
  • ?OR?TO_CHAR(SYSDATE,'HH24')>='17'?THEN??
  • RAISE_APPLICATION_ERROR(-20500,'非法時(shí)間修改表錯(cuò)誤!');??
  • ?????????END?IF;???
  • ????????END;??

  • 執(zhí)行結(jié)果:?
    Sql代碼??
  • 觸發(fā)器已創(chuàng)建。??

  • 步驟2:當(dāng)前時(shí)間為18點(diǎn)50分,在EMP表中插入記錄:?
    Sql代碼??
  • UPDATE?EMP?SET?SAL=3000?WHERE?EMPNO=7369;??

  • 顯示結(jié)果為:?
    Sql代碼??
  • UPDATE?EMP?SET?SAL=3000?WHERE?EMPNO=7369??
  • ???????????????????????????????????????*??
  • ERROR?位于第?1?行:??
  • ????????ORA-20500:?非法時(shí)間修改表錯(cuò)誤!??
  • ????????ORA-06512:?在"STUDENT.CHECK_TIME",?line?5??
  • ????????ORA-04088:?觸發(fā)器?'STUDENT.CHECK_TIME'?執(zhí)行過(guò)程中出錯(cuò)??

  • ? 說(shuō)明:通過(guò)引發(fā)異常限制對(duì)數(shù)據(jù)庫(kù)進(jìn)行的插入、刪除和修改操作的時(shí)間。SYSDATE用來(lái)獲取系統(tǒng)當(dāng)前時(shí)間,并按不同的格式字符串進(jìn)行轉(zhuǎn)換。“DY”表示獲取英文表示的星期簡(jiǎn)寫(xiě),“HH24”表示獲取24小時(shí)制時(shí)間的小時(shí)。?
    當(dāng)在18點(diǎn)50分修改表中的數(shù)據(jù)時(shí),由于時(shí)間在8點(diǎn)至17點(diǎn)(晚5點(diǎn))之外,所以產(chǎn)生“非法時(shí)間修改表錯(cuò)誤”的用戶自定義錯(cuò)誤,修改操作終止。?
    【練習(xí)1】設(shè)計(jì)一個(gè)語(yǔ)句級(jí)觸發(fā)器,限定只能對(duì)數(shù)據(jù)庫(kù)進(jìn)行修改操作,不能對(duì)數(shù)據(jù)庫(kù)進(jìn)行插入和刪除操作。在需要進(jìn)行插入和刪除時(shí),將觸發(fā)器設(shè)置為無(wú)效狀態(tài),完成后重新設(shè)置為生效狀態(tài)。?
    數(shù)據(jù)庫(kù)事件觸發(fā)器 ?
    數(shù)據(jù)庫(kù)事件觸發(fā)器有數(shù)據(jù)庫(kù)級(jí)和模式級(jí)兩種。前者定義在整個(gè)數(shù)據(jù)庫(kù)上,觸發(fā)事件是數(shù)據(jù)庫(kù)事件,如數(shù)據(jù)庫(kù)的啟動(dòng)、關(guān)閉,對(duì)數(shù)據(jù)庫(kù)的登錄或退出。后者定義在模式上,觸發(fā)事件包括模式用戶的登錄或退出,或?qū)?shù)據(jù)庫(kù)對(duì)象的創(chuàng)建和修改(DDL事件)。?
    數(shù)據(jù)庫(kù)事件觸發(fā)器的觸發(fā)事件的種類和級(jí)別如表9-3所示。?
    Sql代碼??
  • 種??類????關(guān)?鍵?字???說(shuō)????明??
  • 模式級(jí)?CREATE??在創(chuàng)建新對(duì)象時(shí)觸發(fā)??
  • ????ALTER???修改數(shù)據(jù)庫(kù)或數(shù)據(jù)庫(kù)對(duì)象時(shí)觸發(fā)??
  • ????DROP????刪除對(duì)象時(shí)觸發(fā)??
  • 數(shù)據(jù)庫(kù)級(jí)????STARTUP?數(shù)據(jù)庫(kù)打開(kāi)時(shí)觸發(fā)??
  • ????SHUTDOWN????在使用NORMAL或IMMEDIATE選項(xiàng)關(guān)閉數(shù)據(jù)庫(kù)時(shí)觸發(fā)??
  • ????SERVERERROR?????發(fā)生服務(wù)器錯(cuò)誤時(shí)觸發(fā)??
  • 數(shù)據(jù)庫(kù)級(jí)與模式級(jí)????LOGON???當(dāng)用戶連接到數(shù)據(jù)庫(kù),建立會(huì)話時(shí)觸發(fā)??
  • ????LOGOFF??當(dāng)會(huì)話從數(shù)據(jù)庫(kù)中斷開(kāi)時(shí)觸發(fā)??

  • 定義數(shù)據(jù)庫(kù)事件和模式事件觸發(fā)器 ?
    創(chuàng)建數(shù)據(jù)庫(kù)級(jí)觸發(fā)器需要ADMINISTER DATABASE TRIGGER系統(tǒng)權(quán)限,一般只有系統(tǒng)管理員擁有該權(quán)限。?
    對(duì)于模式級(jí)觸發(fā)器,為自己的模式創(chuàng)建觸發(fā)器需要CREATE TRIGGER權(quán)限,如果是為其他模式創(chuàng)建觸發(fā)器,需要CREATE ANY TRIGGER權(quán)限。?
    數(shù)據(jù)庫(kù)事件和模式事件觸發(fā)器的創(chuàng)建語(yǔ)法與DML觸發(fā)器的創(chuàng)建語(yǔ)法類似。數(shù)據(jù)庫(kù)事件或模式事件觸發(fā)器的創(chuàng)建語(yǔ)法如下:?
    CREATE [OR REPLACE] TRIGGER 觸發(fā)器名?
    {BEFORE|AFTER }?
    {DDL事件1 [DDL事件2...]| 數(shù)據(jù)庫(kù)事件1 [數(shù)據(jù)庫(kù)事件2...]}?
    ON {DATABASE| [模式名.]SCHEMA }?
    [WHEN (條件)]?
    DECLARE?
    聲明部分?
    BEGIN?
    主體部分?
    END;?
    其中:DATABASE表示創(chuàng)建數(shù)據(jù)庫(kù)級(jí)觸發(fā)器,數(shù)據(jù)庫(kù)級(jí)要給出數(shù)據(jù)庫(kù)事件;SCHEMA表示創(chuàng)建模式級(jí)觸發(fā)器,模式級(jí)要給出模式事件或DDL事件。?
    在數(shù)據(jù)庫(kù)事件觸發(fā)器中,可以使用如表9-4所示的一些事件屬性。不同類型的觸發(fā)器可以使用的事件屬性有所不同。?
    Sql代碼??
  • 屬??性????適用觸發(fā)器類型?說(shuō)????明??
  • Sys.sysevent????所有類型????返回觸發(fā)器觸發(fā)事件字符串??
  • Sys.instance_num????所有類型????返回Oracle實(shí)例號(hào)??
  • Sys.database_name???所有類型????返回?cái)?shù)據(jù)庫(kù)名字??
  • Sys.server_error(stack_position)????SERVERERROR?從錯(cuò)誤堆棧指定位置返回錯(cuò)誤號(hào),參數(shù)為1表示最近的錯(cuò)誤??
  • Is_servererror(error_number)????SERVERERROR?判斷堆棧中是否有參數(shù)指定的錯(cuò)誤號(hào)??
  • Sys.login_user??所有類型????返回導(dǎo)致觸發(fā)器觸發(fā)的用戶名??
  • Sys.dictionary_obj_type?CREATEALTERDROP???返回DDL觸發(fā)器觸發(fā)時(shí)涉及的對(duì)象類型??
  • Sys.?dictionary_obj_name????CREATEALTERDROP???返回DDL觸發(fā)器觸發(fā)時(shí)涉及的對(duì)象名稱??
  • Sys.des_encrypted_password??CREATEALTERDROP???創(chuàng)建或修改用戶時(shí),返回加密后的用戶密碼??

  • 數(shù)據(jù)庫(kù)事件觸發(fā)器 ?
    下面是一個(gè)綜合的數(shù)據(jù)庫(kù)事件觸發(fā)器練習(xí)。先為STUDENT賬戶授予創(chuàng)建數(shù)據(jù)庫(kù)事件觸發(fā)器的權(quán)限,ADMINISTER DATABASE TRIGGER,然后創(chuàng)建有關(guān)的表和觸發(fā)器,最后予以驗(yàn)證。?
    ? 【訓(xùn)練1】? 創(chuàng)建觸發(fā)器,對(duì)本次數(shù)據(jù)庫(kù)啟動(dòng)以來(lái)的用戶登錄時(shí)間進(jìn)行記錄,每次數(shù)據(jù)庫(kù)啟動(dòng)后,先清空該表。?
    步驟1:創(chuàng)建登錄事件記錄表:?
    Sql代碼??
  • CREATE?TABLE?userlog?(??
  • USERNAME?VARCHAR2(20),??
  • LOGON_TIME?DATE);??

  • 執(zhí)行結(jié)果:?
    Sql代碼??
  • 表已創(chuàng)建。??

  • 步驟2:創(chuàng)建數(shù)據(jù)庫(kù)STARTUP事件觸發(fā)器:?
    Sql代碼??
  • CREATE?OR?REPLACE?TRIGGER?INIT_LOGON??
  • AFTER??
  • STARTUP???
  • ON?DATABASE??
  • BEGIN??
  • ?DELETE?FROM?userlog;??
  • END;??

  • 執(zhí)行結(jié)果:?
    Sql代碼??
  • 觸發(fā)器已創(chuàng)建。??

  • 步驟3:創(chuàng)建數(shù)據(jù)庫(kù)LOGON事件觸發(fā)器:?
    Sql代碼??
  • CREATE?OR?REPLACE?TRIGGER?DATABASE_LOGON??
  • AFTER??
  • LOGON???
  • ON?DATABASE??
  • BEGIN??
  • ?INSERT?INTO?userlog???
  • ?VALUES(sys.login_user,sysdate);??
  • END;??

  • 執(zhí)行結(jié)果:?
    Sql代碼??
  • 觸發(fā)器已創(chuàng)建。??

  • 步驟4:驗(yàn)證DATABASE_LOGON觸發(fā)器:?
    Sql代碼??
  • CONNECT?SCOTT/TIGER@MYDB;??
  • ????????CONNECT?STUDENT/STUDENT@MYDB;??

  • 執(zhí)行結(jié)果:?
    Sql代碼??
  • 已連接。??
  • 已連接。??

  • 執(zhí)行查詢:?
    Sql代碼??
  • SELECT?username,TO_CHAR(logon_time,'YYYY/MM/DD?HH24:MI:SS')?FROM?userlog;??

  • 執(zhí)行結(jié)果:?
    Sql代碼??
  • USERNAME?????????????TO_CHAR(LOGON_TIME,??
  • -----------------------------?-----------------------------------------??
  • SCOTT???????????????????2004/03/29?22:42:20??
  • ????????STUDENT?????????????????2004/03/29?22:42:20??

  • 步驟5:驗(yàn)證INIT_LOGON觸發(fā)器。?
    重新啟動(dòng)數(shù)據(jù)庫(kù),登錄STUDENT賬戶:?
    Sql代碼??
  • SELECT?username,TO_CHAR(logon_time,'YYYY/MM/DD?HH24:MI:SS')?FROM?userlog;??

  • 執(zhí)行結(jié)果:?
    Sql代碼??
  • USERNAME?????????????TO_CHAR(LOGON_TIME,??
  • --------------------------------?---------------------------------------??
  • ????????STUDENT??????????????2004/03/29?22:43:59??
  • ????????已選擇?1?行??

  • 說(shuō)明:本例中共創(chuàng)建了兩個(gè)數(shù)據(jù)庫(kù)級(jí)事件觸發(fā)器。DATABASE_LOGON在用戶登錄時(shí)觸發(fā),向表userlog中增加一條記錄,記錄登錄用戶名和登錄時(shí)間。INIT_LOGON在數(shù)據(jù)庫(kù)啟動(dòng)時(shí)觸發(fā),清除userlog表中記錄的數(shù)據(jù)。所以當(dāng)數(shù)據(jù)庫(kù)重新啟動(dòng)后,重新登錄STUDENT賬戶,此時(shí)userlog表中只有一條記錄。?
    【訓(xùn)練2】? 創(chuàng)建STUDENT_LOGON模式級(jí)觸發(fā)器,專門(mén)記錄STUDENT賬戶的登錄時(shí)間:?
    Sql代碼??
  • CREATE?OR?REPLACE?TRIGGER?STUDENT_LOGON???
  • AFTER??
  • LOGON?ON?STUDENT.SCHEMA???
  • BEGIN????
  • ?INSERT?INTO?userlog??
  • ?VALUES(sys.login_user,sysdate);??
  • END;??

  • 執(zhí)行結(jié)果:?
    Sql代碼??
  • 觸發(fā)器已創(chuàng)建。??

  • 說(shuō)明:為當(dāng)前模式創(chuàng)建觸發(fā)器,可以省略SCHEMA前面的模式名。?
    【練習(xí)1】修改DATABASE_LOGON觸發(fā)器和userlog表,增加對(duì)退出時(shí)間的記錄。?
    DDL事件觸發(fā)器 ?
    【訓(xùn)練1】? 通過(guò)觸發(fā)器阻止對(duì)emp表的刪除。?
    步驟1:創(chuàng)建DDL觸發(fā)器:?
    Sql代碼??
  • CREATE?OR?REPLACE?TRIGGER?NODROP_EMP??
  • ?????????BEFORE??
  • ????????DROP?ON?SCHEMA???
  • ????????BEGIN??
  • ????????IF?Sys.Dictionary_obj_name='EMP'?THEN??
  • RAISE_APPLICATION_ERROR(-20005,'錯(cuò)誤信息:不能刪除emp表!');??
  • ?????????END?IF;???
  • ????????END;??

  • 執(zhí)行結(jié)果:?
    Sql代碼??
  • 觸發(fā)器已創(chuàng)建。??

  • 步驟2:通過(guò)刪除emp表驗(yàn)證觸發(fā)器:?
    Sql代碼??
  • DROP?TABLE?emp;??

  • 執(zhí)行結(jié)果:?
    Sql代碼??
  • DROP?TABLE?emp??
  • ????????*??
  • ERROR?位于第?1?行:??
  • ????????ORA-00604:?遞歸?SQL?層?1?出現(xiàn)錯(cuò)誤??
  • ????????ORA-20005:?錯(cuò)誤信息:不能刪除emp表!??
  • ????????ORA-06512:?在line?3??

  • ? ?? 說(shuō)明:該觸發(fā)器阻止在當(dāng)前模式下對(duì)emp表的刪除,但不阻止刪除其他對(duì)象。Sys.Dictionary_obj_name屬性返回要?jiǎng)h除的對(duì)象名稱。?
    替代觸發(fā)器 ?
    【訓(xùn)練1】? 在emp表的視圖上,通過(guò)觸發(fā)器修改emp表。?
    步驟1:創(chuàng)建視圖emp_name:?
    Sql代碼??
  • CREATE?VIEW?emp_name?AS?SELECT?ename?FROM?emp;??

  • 執(zhí)行結(jié)果:?
    Sql代碼??
  • 視圖已建立。??

  • 步驟1:創(chuàng)建替代觸發(fā)器:?
    Sql代碼??
  • CREATE?OR?REPLACE?TRIGGER?change_name??
  • ????????INSTEAD?OF?INSERT?ON?emp_name??
  • ????????DECLARE??
  • V_EMPNO?NUMBER(4);??
  • ????????BEGIN??
  • ????????SELECT?MAX(EMPNO)+1?INTO?V_EMPNO?FROM?EMP;??
  • ????????INSERT?INTO?emp(empno,ename)???
  • ????????VALUES(V_EMPNO,:new.ename);??
  • ????????END;??

  • 執(zhí)行結(jié)果:?
    Sql代碼??
  • 觸發(fā)器已創(chuàng)建。??

  • 步驟2:向emp_name視圖插入記錄:?
    Sql代碼??
  • INSERT?INTO?emp_name?VALUES('BROWN');??
  • ????????COMMIT;??

  • 執(zhí)行結(jié)果:?
    Sql代碼??
  • 已創(chuàng)建?1?行。??
  • ????????提交完成。??

  • ? 說(shuō)明:向視圖直接插入雇員名將會(huì)發(fā)生錯(cuò)誤,因?yàn)閑mp表的雇員編號(hào)列不允許為空。通過(guò)創(chuàng)建替代觸發(fā)器,將向視圖插入雇員名稱轉(zhuǎn)換為向emp表插入雇員編號(hào)和雇員名稱,雇員編號(hào)取當(dāng)前的最大雇員編號(hào)加1。試檢查emp表的雇員列表。?
    【訓(xùn)練2】? 在emp表的視圖emp_name上,通過(guò)觸發(fā)器阻止對(duì)emp表的刪除。?
    步驟1:阻止通過(guò)視圖刪除雇員,并顯示用戶自定義錯(cuò)誤信息:?
    Sql代碼??
  • CREATE?OR?REPLACE?TRIGGER?delete_from_ename??
  • ????????INSTEAD?OF?DELETE?ON?emp_name??
  • ????????BEGIN??
  • ?????????RAISE_APPLICATION_ERROR(-20006,'錯(cuò)誤信息:不能在視圖中刪除emp表的雇員!');??
  • ????????END;??

  • 執(zhí)行結(jié)果:?
    Sql代碼??
  • 觸發(fā)器已創(chuàng)建。??

  • 步驟2:通過(guò)對(duì)視圖進(jìn)行刪除來(lái)驗(yàn)證觸發(fā)器:?
    Sql代碼??
  • DELETE?FROM?emp_name;??

  • 執(zhí)行結(jié)果:?
    Sql代碼??
  • DELETE?FROM?emp_name??
  • ????????????????*??
  • ????????ERROR?位于第?1?行:??
  • ????????ORA-20006:?錯(cuò)誤信息:不能在視圖中刪除emp表的雇員!??
  • ????????ORA-06512:???
  • ????????在"STUDENT.DELETE_FROM_ENAME",?line?2??
  • ????????ORA-04088:?觸發(fā)器?'STUDENT.DELETE_FROM_ENAME'?執(zhí)行過(guò)程中出錯(cuò)??

  • 說(shuō)明:可以通過(guò)視圖emp_name對(duì)雇員進(jìn)行刪除,比如執(zhí)行DELETE FROM emp_name語(yǔ)句將刪除雇員表的全部雇員。但是由于在emp_name視圖中只能看到一部分雇員信息,所以刪除可能會(huì)產(chǎn)生誤操作。通過(guò)定義一個(gè)替代觸發(fā)器,可阻止通過(guò)emp_name視圖對(duì)emp表雇員進(jìn)行刪除,但不阻止直接對(duì)emp表進(jìn)行刪除。?
    查看觸發(fā)器 ?
    【訓(xùn)練1】? 顯示觸發(fā)器CHECK_TIME的體部分:?
    Sql代碼??
  • SELECT?TRIGGER_BODY?FROM?USER_TRIGGERS?WHERE?TRIGGER_NAME='CHECK_TIME';??

  • 結(jié)果為:?
    Sql代碼??
  • TRIGGER_BODY??
  • ????????----------------------------------------------------------------------------------------??
  • ????????BEGIN??
  • ????????IF?(TO_CHAR(SYSDATE,'DY')?IN?('SAT','SUN'))??
  • ?????????OR?TO_CHAR(SYSDATE,'HH24')<??
  • ???????TRIGGER_BODY字段為L(zhǎng)ONG類型,只顯示出腳本的一部分內(nèi)容。??

  • 階段訓(xùn)練 ?
    【訓(xùn)練1】? 創(chuàng)建觸發(fā)器,進(jìn)行表的同步復(fù)制。?
    步驟1:創(chuàng)建emp表的復(fù)本employee:?
    Sql代碼??
  • CREATE?TABLE?employee?AS?SELECT?*?FROM?emp;??

  • 執(zhí)行結(jié)果:?
    Sql代碼??
  • 表已創(chuàng)建。???

  • 步驟2:創(chuàng)建和編譯以下觸發(fā)器:?
    Sql代碼??
  • CREATE?OR?REPLACE?TRIGGER?DUPLICATE_EMP??
  • ????????AFTER???
  • ????????UPDATE?OR?INSERT?OR?DELETE??
  • ????????ON?EMP??
  • ????????FOR?EACH?ROW??
  • ????????BEGIN?????
  • ?????????IF?INSERTING?THEN???
  • ?????????INSERT?INTO?employee???
  • ?????????VALUES(:new.empno,:new.ename,:new.job,:new.mgr,??
  • ???????????:new.hiredate,:new.sal,:new.comm,:new.deptno);??
  • ELSIF?DELETING?THEN??
  • ??DELETE?FROM?employee???
  • ??WHERE?empno=:old.empno;??
  • ?ELSE??
  • ??UPDATE?employee?SET???
  • ??empno=:new.empno,??
  • ??ename=:new.ename,??
  • ??job=:new.job,??
  • mgr=:new.mgr,??
  • ??hiredate=:new.hiredate,??
  • ??sal=:new.sal,??
  • ??comm=:new.comm,??
  • ??deptno=:new.deptno??
  • ??WHERE?empno=:old.empno;??
  • ?END?IF;??
  • END;??

  • 執(zhí)行結(jié)果:?
    Sql代碼??
  • 觸發(fā)器已創(chuàng)建。??

  • 步驟3:對(duì)emp表進(jìn)行插入、刪除和更新:?
    Sql代碼??
  • DELETE?FROM?emp?WHERE?empno=7934;??
  • ????????INSERT?INTO?emp(empno,ename,job,sal)????????VALUES(8888,'ROBERT','ANALYST',2900);??
  • ????????UPDATE?emp?SET?sal=3900?WHERE?empno=7788;??
  • ????????COMMIT;??

  • 執(zhí)行結(jié)果:?
    Sql代碼??
  • 已刪除?1?行。??
  • 已創(chuàng)建?1?行。??
  • 已更新?1?行。??
  • 提交完成。???

  • 步驟4:檢查emp表和employee表中被插入、刪除和更新的雇員。?
    運(yùn)行結(jié)果略,請(qǐng)自行驗(yàn)證。?
    ? 說(shuō)明:在觸發(fā)器中判斷觸發(fā)事件,根據(jù)不同的事件對(duì)employee表進(jìn)行不同的操作。?
    【練習(xí)1】創(chuàng)建一個(gè)emp表的觸發(fā)器EMP_TOTAL,每當(dāng)向雇員表插入、刪除或更新雇員信息時(shí),將新的統(tǒng)計(jì)信息存入統(tǒng)計(jì)表EMPTOTAL,使統(tǒng)計(jì)表總能夠反映最新的統(tǒng)計(jì)信息。?
    統(tǒng)計(jì)表是記錄各部門(mén)雇員總?cè)藬?shù)、總工資的統(tǒng)計(jì)表,結(jié)構(gòu)如下:?
    部門(mén)編號(hào) number(2)?
    總?cè)藬?shù) number(5)?
    總工資 number(10,2)?
    練習(xí) ?
    1. 下列有關(guān)觸發(fā)器和存儲(chǔ)過(guò)程的描述,正確的是:?
    A. 兩者都可以傳遞參數(shù)?
    B. 兩者都可以被其他程序調(diào)用?
    C. 兩種模塊中都可以包含數(shù)據(jù)庫(kù)事務(wù)語(yǔ)句?
    D. 兩者創(chuàng)建的系統(tǒng)權(quán)限不同?
    2. 下列事件,屬于DDL事件的是:?
    ??? A.? INSERT B.? LOGON?
    ??? C.? DROP D.? SERVERERROR?
    3. 假定在一個(gè)表上同時(shí)定義了行級(jí)和語(yǔ)句級(jí)觸發(fā)器,在一次觸發(fā)當(dāng)中,下列說(shuō)法正確的是:?
    ??? A. 語(yǔ)句級(jí)觸發(fā)器只執(zhí)行一次?
    ??? B. 語(yǔ)句級(jí)觸發(fā)器先于行級(jí)觸發(fā)器執(zhí)行?
    ?????????? C. 行級(jí)觸發(fā)器先于語(yǔ)句級(jí)觸發(fā)器執(zhí)行?
    ??????????????? D. 行級(jí)觸發(fā)器對(duì)表的每一行都會(huì)執(zhí)行一次?
    4. 有關(guān)行級(jí)觸發(fā)器的偽記錄,下列說(shuō)法正確的是:?
    ?? A.? INSERT事件觸發(fā)器中,可以使用:old偽記錄。?
    ?? B.? DELETE事件觸發(fā)器中,可以使用:new偽記錄。?
    ?? C.? UPDATA事件觸發(fā)器中,只能使用:new偽記錄。?
    ??????????????? D.? UPDATA事件觸發(fā)器中,可以使用:old偽記錄。?
    5. 下列有關(guān)替代觸發(fā)器的描述,正確的是:?
    ??? A. 替代觸發(fā)器創(chuàng)建在表上?
    ??????????????? B. 替代觸發(fā)器創(chuàng)建在數(shù)據(jù)庫(kù)上?
    ??????????????? C. 通過(guò)替代觸發(fā)器可以向基表插入數(shù)據(jù)?
    ??????????????? D. 通過(guò)替代觸發(fā)器可以向視圖插入數(shù)據(jù)?

    總結(jié)

    以上是生活随笔為你收集整理的oracle 触发器的种类和触发事件的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。