2016-04-19 44 views
0

我的問題如下, 首先這裏是我的代碼,如何通過觸發器本身刪除關於哪個觸發器被調用的行?

create or replace trigger tri_ISSUE 
after insert or delete 
on ISSUE 
for each row 
declare 
    ct varchar2(20); 
    cnt number(20); 
begin 
    if inserting 
    then 
     select bk_category into ct from BOOK_MASTER where accn_no=:new.accn_no; 
     select available into cnt from BOOK_INFO where bk_category=ct; 
     if(cnt=0) 
     then 
      dbms_output.put_line('Book is not available!'); 
      delete ISSUE where rollno=:new.rollno and accn_no=:new.accn_no; 
     else 
      select bk_category into ct from BOOK_MASTER where accn_no=:new.accn_no; 
      update BOOK_INFO set available=available-1 where bk_category=ct; 
     end if; 
    end if; 
    if deleting 
    then 
     select bk_category into ct from BOOK_MASTER where accn_no=:old.accn_no; 
     update BOOK_INFO set available=available+1 where bk_category=ct; 
    end if; 
end; 

我得到這樣的錯誤,

ORA-04091: table SYSTEM.ISSUE is mutating, trigger/function may not see it 
ORA-06512: at "SYSTEM.TRI_ISSUE", line 12 
ORA-04088: error during execution of trigger 'SYSTEM.TRI_ISSUE' 

什麼,我試圖做的是,我要刪除通過插入後觸發的'After Insert'觸發器插入正在插入的行。我可以這樣做嗎?任何人都可以建議我補救嗎?在此先感謝:)

+1

不,你不能。你可以引發一個異常來阻止'insert'成功。您可以(取決於Oracle版本)使用before語句,row-level和after語句部分在觸發器的after語句部分中執行刪除的複合觸發器。這給系統增加了很多複雜性。爲什麼你想首先將這個邏輯放在觸發器中,而不是讓實現檢出的代碼驗證該書實際上是否可用? –

回答

0

有幾種方法來實現您的要求。

  1. 把你所有的邏輯放到一個過程中。這很可能是最好的做法。
  2. 通過raise_application_error(-20001, 'Book is not available!');

    更換線delete ISSUE where rollno = :new.rollno and accn_no = :new.accn_no;利用該用戶得到一個異常並且數據不被插入。

  3. 創建一個compound triggerBEFORE STATEMENT,BEFORE EACH ROWAFTER STATEMENT組件。
  4. 創建一個視圖和INSTEAD OF TRIGGER,會是這樣:

    CREATE OR REPLACE VIEW V_ISSUE AS 
    SELECT * FROM ISSUE; 
    
    CREATE OR REPLACE TRIGGER tri_ISSUE 
        INSTEAD OF INSERT OR DELETE ON V_ISSUE 
        FOR EACH ROW 
    
    declare 
        ct varchar2(20); 
        cnt number(20); 
    begin 
        if inserting 
        then 
         select bk_category into ct from BOOK_MASTER where accn_no=:new.accn_no; 
         select available into cnt from BOOK_INFO where bk_category=ct; 
         if(cnt=0) 
         then 
          dbms_output.put_line('Book is not available!'); 
          NULL; -- > do nothing 
         else 
          INSERT INTO ISSUE VALUES (... all coloums of this table); 
          select bk_category into ct from BOOK_MASTER where accn_no=:new.accn_no; 
          update BOOK_INFO set available=available-1 where bk_category=ct; 
         end if; 
        end if; 
        if deleting 
        then 
         DELETE FROM ISSUE WHERE ...; 
         select bk_category into ct from BOOK_MASTER where accn_no=:old.accn_no; 
         update BOOK_INFO set available=available+1 where bk_category=ct; 
        end if; 
    END;