触发后插入

时间:2013-11-21 17:38:53

标签: oracle plsql

我需要在历史数据表中插入'注册',当我在'ALUGUER'中插入内容时,触发器应在'HISTORICO'中插入一行:

我的触发器:

create or replace 
trigger ADD_HISTORICO
AFTER INSERT
   ON ALUGUER
   FOR EACH ROW

DECLARE
   cod_aluguer_p NUMBER(6,0);
   cod_veiculo_p NUMBER(6,0);
BEGIN

   SELECT ID_ALUGUER INTO cod_aluguer_p
   FROM ALUGUER;
   SELECT COD_VEICULO INTO cod_veiculo_p
   FROM ALUGUER;

   INSERT INTO HISTORICO(ID_ENTRADA,DESCRICAO,DATA_REGISTO,NOVO_VEICULO,NOVO_ALUGUER)
   VALUES(SEQ_HISTORICO.nextval,'NOVA DESCRIÇÃO','21/11/2013',cod_veiculo_p,cod_aluguer_p);

END;

错误报告:

  

SQL错误:
  ORA-04091:BDDAD_DL1.ALUGUER表是变异的,触发器可以   不读或修改   ORA-06512:在“BDDAD_DL1.ADD_HISTORICO”,第6行   ORA-04088:执行触发器'BDDAD_DL1.ADD_HISTORICO'时出错   04091. 00000 - 。 “表%s%s正在发生变异,触发/功能可能看不到它”   *原因:触发器(或用户定义的plsql函数,在   这句话)试图查看(或修改)表格是否为
  在被解雇它的声明修改的过程中   *动作:重写触发器(或函数),使其不读取该表。

2 个答案:

答案 0 :(得分:2)

您正在尝试从触发器触发的表中读取记录。这是禁忌。所以,这段代码:

   SELECT ID_ALUGUER INTO cod_aluguer_p
   FROM ALUGUER;
   SELECT COD_VEICULO INTO cod_veiculo_p
   FROM ALUGUER;

是不允许的。而且,没有意义,因为select上没有WHERE子句,所以 将返回所有行。模仿点,无论如何你不能这样做。你想要做的是引用:触发行的新值istead。例如:

   cod_aluguer_p := :new.ID_ALUGUER ;
   cod_veiculo_p L= :NEW.COD_VEICULO;

此外,您甚至不需要那些局部变量,只需直接使用:new。

   INSERT INTO HISTORICO(ID_ENTRADA,DESCRICAO,DATA_REGISTO,NOVO_VEICULO,NOVO_ALUGUER)
   VALUES(SEQ_HISTORICO.nextval,'NOVA DESCRIÇÃO','21/11/2013',:NEW.COD_VEICULO,:new.ID_ALUGUER );

我建议您阅读Oracle docs on triggers

答案 1 :(得分:1)

不需要SELECT,只需参考触发器中的:NEW值即可。此外,您可以使用TRUNC(SYSDATE)来获取当前日期,假设这是您的意图:

create or replace 
trigger ADD_HISTORICO
AFTER INSERT
   ON ALUGUER
   FOR EACH ROW

BEGIN

   INSERT INTO HISTORICO(ID_ENTRADA,DESCRICAO,DATA_REGISTO,
           NOVO_VEICULO,NOVO_ALUGUER)
   VALUES(SEQ_HISTORICO.nextval,'NOVA DESCRIÇÃO',
          TRUNC(SYSDATE),:NEW.COD_VEICULO ,:NEW.ID_ALUGUER );

END;