31

它我有一个名为per的表。在每个表中,我有一个名为“fl1”的字段和另一个名为“fl2”的字段。更新记录时,我想检查“fl1”的值是否已更改。如果值已更改,请使用“fl1”中的新值更新“fl2”列。

我想出了这个触发器

CREATE OR REPLACE TRIGGER Flag
AFTER INSERT OR UPDATE on per
REFERENCING NEW AS NEW OLD AS OLD
BEGIN
  If :New.fl1 != :Old.fl1 Then
        :New.fl2:= :new.fl1;
  End If;
END;

当我运行它时,我得到一个“ORA-04082:表级触发器中不允许新或旧引用”

我正在考虑的另一个选项(不确定它是否有效)是简单地用“fl1”的值更新“fl2”的值,而不管“fl1”的值是否已经改变。

更新

添加了“每行”并将“插入或更新后”更改为“插入或更新前”。它正在工作。

CREATE OR REPLACE TRIGGER Flag
BEFORE INSERT OR UPDATE on per
REFERENCING NEW AS NEW OLD AS OLD

FOR EACH ROW
BEGIN
If :New.fl1 != :Old.fl1 Then
   :New.fl2:= :new.fl1;
End If;
END;
4

2 回答 2

31

DML 触发器被定义为表级别或行级别。

表级触发器为表上的每个操作触发一次,因此如果更新 30 行,那么就表触发器而言,这是一个操作。表触发器无法洞察哪些行被修改,但可用于记录执行操作的事实。

在这种情况下,您需要一个行级触发器,它要求在触发器定义中包含“FOR EACH ROW”。如果您不想更改引用新行和旧行的方式,则“REFERENCING”子句是可选的。

http://docs.oracle.com/cd/B28359_01/appdev.111/b28370/triggers.htm#BABCIBBJ

不过,不确定这里练习的目的是什么。您是否考虑过仅引用 fl1 而不是 fl2?

于 2013-09-11T12:35:22.760 回答
7

最终工作代码:

CREATE OR REPLACE TRIGGER Flag
BEFORE INSERT OR UPDATE on per
REFERENCING NEW AS NEW OLD AS OLD

FOR EACH ROW
BEGIN
If :New.fl1 != :Old.fl1 Then
   :New.fl2:= :new.fl1;
End If;
END;
于 2013-09-11T17:54:03.183 回答