【问题标题】:Update with after insert trigger on same table在同一张表上使用插入后触发器进行更新
【发布时间】:2011-10-19 00:47:08
【问题描述】:

我要在 tableA 上编写一个插入触发器。这将使用相同的表但不同的列执行更新。执行此操作时出现错误。我的触发器是

create or replace trigger trigger_A
after insert on table_A
begin
  update table_A set col1=1 where col1 is null;
end;

我有一个应用程序将单独执行 col2 将被插入,而 col1 将保持为空。所以一旦插入行,我的触发器将为 col1 提供值。但是当插入一行时,我收到错误消息“触发器失败且无效”。 这个怎么做。 TIA。

【问题讨论】:

  • 首先,尝试Col1 IS NULLNOTHING 等于 (=) NULL,甚至不等于 NULL。虽然我不相信这是你错误的根源。
  • @Dems - 更改了我的代码!

标签: sql oracle triggers


【解决方案1】:

如果你想分配一个简单的默认值,最简单的方法是在表上声明它,使用 DEFAULT 子句。

SQL> create table t42
  2    ( col1 number default 1 not null
  3      , col2 date)
  4  /

Table created.

SQL> insert into t42 (col2) values (sysdate)
  2  /

1 row created.

SQL> select * from t42
  2  /

      COL1 COL2
---------- ---------
         1 03-AUG-11

SQL>

这适用于文字或伪列,例如 SYSDATE 或 USER。如果要使用用户定义的函数或序列导出更复杂的值,则需要使用 触发器。

这是一个新版本的表格...

SQL> create table t42
  2    ( col1 number default 1 not null
  3      , col2 date default sysdate
  4      , col3 varchar2(30) default user
  5      , col4 number )
  6  /

Table created.

SQL>

...带有触发器:

SQL> create or replace trigger t42_trg
  2      before insert or update
  3      on t42
  4      for each row
  5  begin
  6      if :new.col4 is null
  7      then
  8          :new.col4 := my_seq.nextval;
  9      end if;
 10  end;
 11  /

Trigger created.

SQL> insert into t42 (col1, col2, col3)
  2  values (99, sysdate, 'MR KNOX')
  3  /

1 row created.

SQL> select * from t42
  2  /

      COL1 COL2      COL3                                 COL4
---------- --------- ------------------------------ ----------
        99 03-AUG-11 MR KNOX                               161

SQL>

请注意,虽然表中的每一列都是可默认的,但我必须填充至少一列以使 SQL 有效:

SQL> insert into t42 values ()
  2  /
insert into t42 values ()
                        *
ERROR at line 1:
ORA-00936: missing expression


SQL>

但我可以将 NULL 传递给 COL4 以获得完全默认的记录:

SQL> insert into t42 (col4) values (null)
  2  /

1 row created.

SQL> select * from t42
  2  /

      COL1 COL2      COL3                                 COL4
---------- --------- ------------------------------ ----------
        99 03-AUG-11 MR KNOX                               161
         1 03-AUG-11 APC                                   162

SQL>

警告讲师:我的触发器使用新的 11g 语法。在以前的版本中,我们必须使用 SELECT 语句来分配序列值:

select my_seq.nextval
into :new.col4
from dual;

【讨论】:

    【解决方案2】:

    您无法更新调用触发器的表:

    在存储的函数或触发器中,不允许修改 已被(用于读取或写入)的表 调用函数或触发器的语句。

    这样做会产生错误 1442:

    Error Code: 1442
    Can't update table 'MyTable' in stored function/trigger because it is already used by statement which invoked this stored function/trigger.
    

    简而言之,我们不允许更新正在使用的表-但您的情况很简单,只想更新为NULL的字段,为此选择BEFORE INSERT ON触发器,这样您就可以更新所有字段新的/当前的条目/行(因为它还没有被输入):

    DELIMITER //
    DROP TRIGGER IF EXISTS trigger_A//
    CREATE TRIGGER trigger_A BEFORE INSERT ON table_A
    FOR EACH ROW BEGIN
        IF NEW.col1 IS NULL THEN
            set NEW.col1 = <some-value>;
        ENF IF;
    END;
    //
    DELIMITER ;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-12-18
      • 1970-01-01
      • 1970-01-01
      • 2019-08-20
      • 1970-01-01
      • 2016-12-14
      • 2011-07-17
      • 1970-01-01
      相关资源
      最近更新 更多