插入到执行触发器(插入之前)的同一表中

时间:2018-07-31 17:10:54

标签: sql oracle triggers duplicates database-trigger

我必须执行一个触发器,该触发器必须两次写入同一列,但具有一个不同的值,例如:

插入前的语句为:

BEFORE INSERT ON MXGLCOMP_CLOUD

我收到的数据是:12345,RAIL,075,HDFG

但是,我也想将相同的数据插入MXGLCOMP_CLOUD,但是像这样: 12345,RAIL,069,HDFG。

我编写了以下代码,但由于我在同一触发器中执行插入操作,恐怕触发器将陷入无限循环。

create or replace TRIGGER MXGLCOMP_CLOUD_TRG 
BEFORE INSERT ON MXGLCOMP_CLOUD 
REFERENCING OLD AS OLD NEW AS NEW 
FOR EACH ROW 
BEGIN
    INSERT INTO MXGLCOMP_CLOUD (ACTIVE, COMPTEXT, COMPVALUE, EXTERNALREFID)
    VALUES (:NEW.ACTIVE, :NEW.COMPTEXT, '069', :NEW.EXTERNALREFID);
END;

可以吗?我该怎么办?就像我之前说的,我没有运行测试,因为我不想那个无限循环。

1 个答案:

答案 0 :(得分:0)

您已经怀疑,您的当前代码将循环,因为触发器内的插入将导致触发器再次触发,并且将执行另一次插入,这将导致触发器触发,从而……等等。但是Oracle会在发现发生的情况时间接终止它:

 ORA-00036: maximum number of recursive SQL levels (50) exceeded
 ORA-06512: at "SCHEMA.MXGLCOMP_CLOUD_TRG", line 7

在这种情况下,避免这种情况很简单:只需检查要插入的值,并仅在'075'处插入另一行:

create or replace trigger mxglcomp_cloud_trg 
before insert on mxglcomp_cloud 
for each row 
begin
  if :new.compvalue = '075' then
    insert into mxglcomp_cloud(active, comptext, compvalue, externalrefid)
    values(:new.active, :new.comptext, '069', :new.externalrefid);
  end if;
end;
/

然后将单个插入到空表中将创建两行:

insert into mxglcomp_cloud (active, comptext, compvalue, externalrefid)
values (12345, 'RAIL', '075', 'HDFG');

1 row inserted.

select * from mxglcomp_cloud;

    ACTIVE COMPTEXT   COM EXTERNALRE
---------- ---------- --- ----------
     12345 RAIL       069 HDFG      
     12345 RAIL       075 HDFG      

但是,我仍然认为这不是一个好主意,您隐藏了业务逻辑和数据操纵,并且会产生用户可能无法预期的副作用。举一个明显的例子,当实际有两个插入内容时,插入内容报告“已插入1行”。

最好从应用程序层执行两次插入,或者将两者都放入一个过程中,然后让应用程序(以及其他所有人)调用它。


如果您实际上想将'GB'更改为两行,其中一行包含'075',另一行包含'069',则可以执行相同的操作,但需要测试'GB'将其值更改为'075',同时仍然插入多余的行:

create or replace trigger mxglcomp_cloud_trg 
before insert on mxglcomp_cloud 
for each row 
begin
  if :new.compvalue = 'GB' then
    -- change this row from GB to 075
    :new.compvalue := '075';

    -- add another row for 069
    insert into mxglcomp_cloud(active, comptext, compvalue, externalrefid)
    values(:new.active, :new.comptext, '069', :new.externalrefid);
  end if;
end;
/

然后(再次从一个空表开始):

insert into mxglcomp_cloud (active, comptext, compvalue, externalrefid)
values (12345, 'RAIL', 'GB', 'HDFG');

1 row inserted.

select * from mxglcomp_cloud;

    ACTIVE COMPTEXT   COM EXTERNALRE
---------- ---------- --- ----------
     12345 RAIL       069 HDFG      
     12345 RAIL       075 HDFG