【问题标题】:Simple oracle triggers简单的预言机触发器
【发布时间】:2011-04-11 14:24:59
【问题描述】:

简单的一个。我是 PLSql 的新手,oracle 的错误消息永远不会太有帮助。

我想做一个简单的触发器来更新具有当前日期的列,即表的“修改日期”列。但是遇到了一个奇怪的错误。

想法很简单

create table test1 (tcol varchar2(255), tcol2 varchar2(255))

CREATE OR REPLACE TRIGGER testTRG
AFTER INSERT OR UPDATE ON test1
FOR EACH ROW
BEGIN 
     update test1
     set tcol2 =  to_char(sysdate)
     where tcol = :OLD.tcol;
END;

insert into test1 (tcol) values ('test1');

这会弹出错误:

ORA-04091: table RAIDBIDAT_OWN.TEST1 is mutating, trigger/function may not see it
ORA-06512: at "RAIDBIDAT_OWN.TESTTRG", line 2
ORA-04088: error during execution of trigger 'RAIDBIDAT_OWN.TESTTRG'

有人能快速解决这个问题吗?

干杯,

f.

【问题讨论】:

  • 既然你说表有一个目标列的varchar,我建议你做to_char(sysdate, <date_time_mask>,即to_char(sysdate, 'YYYY-MM-DD HH24:Mi:SS'),以明确存储日期的格式,而不是隐含接受NLS_DATE_FORMAT,对于不同的会话可能不同。

标签: oracle plsql triggers ora-04091 mutating-table


【解决方案1】:

你的情况:

SQL> create table test1 (tcol varchar2(255), tcol2 varchar2(255))
  2  /

Table created.

SQL> CREATE OR REPLACE TRIGGER testTRG
  2  AFTER INSERT OR UPDATE ON test1
  3  FOR EACH ROW
  4  BEGIN
  5       -- Your original trigger
  6       update test1
  7       set tcol2 =  to_char(sysdate)
  8       where tcol = :OLD.tcol;
  9  END;
 10  /

Trigger created.

SQL> insert into test1 (tcol) values ('test1');
insert into test1 (tcol) values ('test1')
            *
ERROR at line 1:
ORA-04091: table [schema].TEST1 is mutating, trigger/function may not see it
ORA-06512: at "[schema].TESTTRG", line 3
ORA-04088: error during execution of trigger '[schema].TESTTRG'

Tony 的建议几乎是正确的,但不幸的是它没有编译:

SQL> CREATE OR REPLACE TRIGGER testTRG
  2  AFTER INSERT OR UPDATE ON test1
  3  FOR EACH ROW
  4  BEGIN
  5       -- Tony's suggestion
  6       :new.tcol2 :=  sysdate;
  7  END;
  8  /
CREATE OR REPLACE TRIGGER testTRG
                          *
ERROR at line 1:
ORA-04084: cannot change NEW values for this trigger type

因为您只能在 before-each-row 触发器中更改 NEW 值:

SQL> create or replace trigger testtrg
  2    before insert or update on test1
  3    for each row
  4  begin
  5    :new.tcol2 := sysdate;
  6  end;
  7  /

Trigger created.

SQL> insert into test1 (tcol) values ('test1');

1 row created.

SQL> select * from test1
  2  /

TCOL
------------------------------------------------------------------------------------------
TCOL2
------------------------------------------------------------------------------------------
test1
13-09-2010 12:37:24


1 row selected.

问候, 抢。

【讨论】:

    【解决方案2】:

    触发器应该简单地写成:

    CREATE OR REPLACE TRIGGER testTRG
    BEFORE INSERT OR UPDATE ON test1
    FOR EACH ROW
    BEGIN 
         :new.tcol2 :=  to_char(sysdate);
    END;
    

    没有要求发布同一行的另一个更新(正如您所发现的,您不能)。

    更常见的是使用 DATE 列来存储日期:

    create table test1 (tcol varchar2(255), tcol2 date);
    
    CREATE OR REPLACE TRIGGER testTRG
    BEFORE INSERT OR UPDATE ON test1
    FOR EACH ROW
    BEGIN 
         :new.tcol2 :=  sysdate;
    END;
    

    【讨论】:

    • 你确定那是sintax吗?现在得到这个:2/17 PLS-00103:在期待以下之一时遇到符号“=”::=。 ( @ % ; 指标 3/1 PLS-00103: 遇到符号“END”
    • 哦,关于日期的事情……我同意你的看法。只是碰巧实际表具有该列的 varchar,并且由于其他原因我无法更改它。但是谢谢:)
    • 哦..我复制了第一个编辑。它缺少“:”。对不起我的新手:(
    • 重新语法,我第一次发帖时确实犯了一个错误,但后来通过将“=”更改为“:="/
    猜你喜欢
    • 2014-01-05
    • 1970-01-01
    • 1970-01-01
    • 2013-01-29
    • 2020-04-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多