2017-07-25 78 views
0

我插入到表:更新插入的行與觸發

fruit: 

fruit_id | name 
-----------|---------- 
1   | apple 
---------------------- 

,我有另一個表:

basket: 

basket_id | fruit_id | name 
------------|--------------|----------- 
345   | 1   | apple 
789   | 2   | grape 

當我插入:

insert into fruit (fruit_id) values (2) 

我想更新「名稱」列基於籃子表中的名稱。

我想用這個觸發器來做到這一點:當我嘗試使用這個觸發插入

create trigger add_fruit_name 
after insert 
    on fruit 
    for each row 
DECLARE 
BEGIN 
    update fruit 
    set (name) = 
    (select name from basket 
    where :new.fruit_id = basket.fruit_id); 
    commit; 
END; 
/

我的錯誤是這樣的:

table FRUIT is mutating, trigger/function may not see it 

什麼想法?

+2

您不能在不使用自治事務的情況下,改變與該表關聯的基於行的觸發器內部的表。使用before觸發器,並直接設置:new row列的值? –

+0

你是對的,謝謝。 – user3329046

回答

1

變異觸發器意味着數據在觸發器觸發時發生變化,在你的情況下,你正在更新(DML操作)同一個表,插入(DML操作)到同一個表中,這意味着觸發器不會看到這可能,因此錯誤+它有一個提交,沒有這是在AUTONOMOUS_TRANSATION(閱讀更多關於該PRAGMA瞭解它)。 現在,作爲一般規則,觸發器不應該提交,除非它們處於自治事務中,這是通過聲明上述PRAGMA(僅在極端情況下)完成的。 我會寫觸發像這樣:

create trigger add_fruit_name 
before insert 
    on fruit 
    for each row 
DECLARE 
BEGIN 
    select b.name 
     into :new.name 
     from basket b 
    where b.fruit_id = :new.fruit_id; 

    EXCEPTION 
    WHEN NO_DATA_FOUND THEN 
     raise_application_error (-20001,'No fruit found in table basket for fruit_id: ' || to_char(:new.fruit_id)); 
    WHEN OTHERS THEN 
     raise_application_error (-20002, 'Trigger add_fruit_name raised an error' || SQLERRM); 

END; 
/

另一種方法是編輯功能/程序中插入行的成果表,並使其適當地更新。

一個小而重要的文章理解 - check this out

乾杯

+0

觸發器應該是在插入之前。你的觸發器不會編譯:'ORA-04084:無法更改此觸發器類型的NEW值 – APC

+0

已更正 - 謝謝@APC! – g00dy