【问题标题】:Update inserted row with trigger使用触发器更新插入的行
【发布时间】:2017-07-25 21:13:00
【问题描述】:

我正在插入表格:

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

有什么想法吗?

【问题讨论】:

  • 如果不使用自治事务,您无法从与该表关联的基于行的触发器内部更改该表。使用前触发器,直接设置:new row列的值?
  • 你是对的,谢谢。

标签: oracle plsql database-trigger


【解决方案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

干杯

【讨论】:

  • 触发器应该在插入之前。您的触发器无法编译:ORA-04084: cannot change NEW values for this trigger type
猜你喜欢
  • 2015-09-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-03-08
  • 2017-06-26
相关资源
最近更新 更多