2017-07-25 76 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