【问题标题】:Mutating Trigger Oracle变异触发预言机
【发布时间】:2014-01-05 04:58:15
【问题描述】:

我有两张桌子mainhist。我想从main 表中复制一行,只要它的日期时间列被修改为hist,并将main 中的修改列重置为null,除了一列。但是我得到了变异触发错误。请帮忙。 下面是两个触发器,

CREATE OR REPLACE TRIGGER INS_HIS
AFTER UPDATE OF datetime ON main
FOR EACH ROW 
  INSERT INTO HIST 
    VALUES (Col2 = :new.col2, Col3= :new.Col3)
END;


CREATE OR REPLACE TRIGGER UPD_NUL_MAIN
AFTER INSERT ON HIST
FOR EACH ROW
   UPDATE Main 
      SET (Col2 = NULL
           Col3= NULL)
    WHERE HIST.datetime = main.datetime;
END

【问题讨论】:

  • 嘿 Rob,我认为错误是第二次触发,列被复制到 hist 表,但之后当它必须使主列为空时它不起作用。
  • 是的 - 我看到了我的方式错误(我没有注意到数据时间的更新后)并删除了原始评论。

标签: oracle triggers mutating-table


【解决方案1】:

假设您只想更改 main 中触发更新的行,如果您将第一个触发器更改为 BEFORE UPDATE 并在此处设置 col2 和 col3,则可以完全摆脱第二个触发器:

CREATE OR REPLACE TRIGGER INS_HIS
BEFORE UPDATE OF datetime ON main
FOR EACH ROW          
BEGIN
  INSERT INTO HIST
    (col2,
     col3)
  VALUES
    (:new.col2,
     :new.Col3);
  :new.col2 := NULL;
  :new.col3 := NULL;
END;

顺便说一句:您的触发器语法错误 - 您不能使用 (col2 = :new.col2)。

【讨论】:

  • 道歉 - 写帖子时分心了,看起来我提交了重复的答案!
  • 没问题,经常发生在我身上:-)
  • 哦,是的,你的语法是对的,我的错,但同一个触发器中的 null 事情不会发生
  • @user3110283 你真的尝试过(作为更新前触发器)吗?如果是的话,究竟是什么不适合你?
【解决方案2】:

为了做到这一点,我认为您只需要一个触发器?

CREATE OR REPLACE TRIGGER ins_his BEFORE UPDATE OF datetime ON main
FOR EACH ROW 
BEGIN

  INSERT INTO hist ( col2     , col3      )
            VALUES ( :new.col2, :new.col3 );

  :new.col2 := NULL;
  :new.col3 := NULL;

END;
/

示例输出:

SQL*Plus: Release 11.2.0.1.0 Production on Tue Dec 17 13:17:08 2013

Copyright (c) 1982, 2010, Oracle.  All rights reserved.


Connected to:
Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 - 64bit Production
With the Partitioning, Real Application Clusters, Automatic Storage Management,
OLAP,
Data Mining and Real Application Testing options

SQL> create table main ( datetime DATE, col2 NUMBER, col3 NUMBER );

Table created.

SQL> create table hist ( col2 NUMBER, col3 NUMBER );

Table created.

SQL> CREATE OR REPLACE TRIGGER ins_his BEFORE UPDATE OF datetime ON main
  2  FOR EACH ROW
  3  BEGIN
  4    --
  5    INSERT INTO hist ( col2     , col3      )
  6              VALUES ( :new.col2, :new.col3 );
  7    --
  8    :new.col2 := NULL;
  9    :new.col3 := NULL;
 10    --
 11  END;
 12  /

Trigger created.

SQL> insert into main( datetime, col2, col3 )
  2  values ( sysdate, 5, 10 );

1 row created.

SQL> select * from main;

DATETIME        COL2       COL3
--------- ---------- ----------
17-DEC-13          5         10

SQL> select * from hist;

no rows selected

SQL> update main set datetime = sysdate-1;

1 row updated.

SQL> select * from main;

DATETIME        COL2       COL3
--------- ---------- ----------
16-DEC-13

SQL> select * from hist;

      COL2       COL3
---------- ----------
         5         10

SQL>

【讨论】:

  • 您确定这适用于 AFTER UPDATE 触发器(而不是 BEFORE UPDATE 触发器)吗?
  • 啊,我不认为我们可以在同一个触发器中将值更改为 null。它不会发生,因为事件在主表上
  • 我还有一个问题,每次向主表添加列时,我都必须编辑触发器,有什么方法可以选择要复制的主表中的所有列无论我何时添加或删除它们?
  • @user3110283 请不要在 cmets 中提出其他问题。如果您的问题已解决,请接受其中一个答案,然后在 SO (StackOverflow) 上发布其他问题。
  • 哦,对不起,没意识到。 SO新手。谢谢。
猜你喜欢
  • 1970-01-01
  • 2011-04-11
  • 2020-04-13
  • 2014-07-07
  • 2018-02-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多