【问题标题】:Trying to read a table on Trigger during update, giving mutation error尝试在更新期间读取触发器上的表,给出突变错误
【发布时间】:2019-10-12 02:11:00
【问题描述】:

在更新表之前,我必须在另一个表中插入,但要完成此操作,我需要来自我正在更新的表(和其他表)的信息,尝试在触发器中读取我的更新表会给出错误

第 1 行的错误: ORA-04091: 表 BASEDATOS2.SOL_SOLICITUD_PREMIOS 正在变异,触发器/函数 可能看不到 ORA-06512: 在“BASEDATOS2.INS_AFTER_UPD_PRICES”第 10 行 ORA-04088: 执行触发器 'BASEDATOS2.INS_AFTER_UPD_PRICES' 期间出错

这是我的触发器

    CREATE OR REPLACE TRIGGER INS_AFTER_UPD_PRICES BEFORE UPDATE OF CONCEDIDO ON SOL_SOLICITUD_PREMIOS 
FOR EACH ROW WHEN (new.CONCEDIDO = 'S')
DECLARE
    DESDE DATE;
    HASTA DATE;
    MONTO NUMBER;
    MAX_ID NUMBER;
    v_mov_premio NUMBER;
    CUENTA NUMBER;
BEGIN
    SELECT MAX(ID_MOVIMIENTO)+1 INTO MAX_ID FROM AHO_MOVIMIENTOS_CUENTA;
    SELECT SSP.FECHA_DESDE,SSP.FECHA_HASTA,SE.MONTO_COBERTURA INTO DESDE,HASTA,MONTO
    FROM SOL_SOLICITUD_PREMIOS SSP JOIN SOL_EVENTOS SE
    ON SE.COD_EVENTO = SSP.COD_EVENTO 
    WHERE SE.COD_EVENTO=:OLD.COD_EVENTO
    AND SSP.ID=:OLD.ID;

    select id_tipo into v_mov_premio
            from aho_tipo_movimiento
            where UPPER(nombre_tipo) like '%PAGO DE PREMIO/SUBSIDIO%';

    SELECT AM.ID_CUENTA INTO CUENTA 
    FROM AHO_MOVIMIENTOS_CUENTA AM
    JOIN AHO_TIPO_MOVIMIENTO ATM ON ATM.ID_TIPO=AM.ID_TIPO
    WHERE ATM.ID_TIPO='A' AND ROWNUM=1;

    INSERT INTO AHO_MOVIMIENTOS_CUENTA 
    VALUES(MAX_ID, SYSDATE, MONTO*(HASTA-DESDE),v_mov_premio,CUENTA );
END;

有人知道我怎样才能让它工作吗?

【问题讨论】:

  • 您的表正在变异,因为您正在更新它。因此,在触发器中对该表使用 select 是无效的。将该逻辑移出触发器。
  • 我不知道如何将逻辑移出仍然使其工作
  • 您可以编写一个匿名块、存储过程、包等。它将在事务下在触发器之外执行所有这些操作。即使在触发器中执行如此多的 SQL 也不是一个好主意

标签: oracle plsql mutating-table


【解决方案1】:

这里的问题是您的触发器是在 SOL_SOLICITUD_PREMIOS 上定义的,并且在触发器的主体中,您正在从 SOL_SOLICITUD_PREMIOS 中选择数据。在 ROW 触发器中,不允许读取、插入、更新或删除定义触发器的表中的其他行,因为它可能导致触发器循环,其中数据库在评估同一触发器的递归调用时会卡住。但是,在这种情况下,不需要从 SOL_SOLICITUD_PREMIOS 读取数据,因为您已经在 :OLD 伪行中获得了所需的数据。如果我阅读正确,您可以按如下方式重写您的触发器,它应该可以满足您的要求:

CREATE OR REPLACE TRIGGER INS_AFTER_UPD_PRICES
  BEFORE UPDATE OF CONCEDIDO ON SOL_SOLICITUD_PREMIOS 
  FOR EACH ROW
  WHEN (new.CONCEDIDO = 'S')
DECLARE
    MONTO         NUMBER;
    MAX_ID        NUMBER;
    v_mov_premio  NUMBER;
    CUENTA        NUMBER;
BEGIN
    SELECT MAX(ID_MOVIMIENTO)+1 INTO MAX_ID FROM AHO_MOVIMIENTOS_CUENTA;

    SELECT SE.MONTO_COBERTURA
      INTO MONTO
      FROM SOL_EVENTOS SE 
      WHERE SE.COD_EVENTO = :OLD.COD_EVENTO;

    select id_tipo
      into v_mov_premio
      from aho_tipo_movimiento
      where UPPER(nombre_tipo) like '%PAGO DE PREMIO/SUBSIDIO%';

    SELECT AM.ID_CUENTA
      INTO CUENTA 
      FROM AHO_MOVIMIENTOS_CUENTA AM
      JOIN AHO_TIPO_MOVIMIENTO ATM
        ON ATM.ID_TIPO = AM.ID_TIPO
      WHERE ATM.ID_TIPO = 'A' AND
            ROWNUM = 1;

    INSERT INTO AHO_MOVIMIENTOS_CUENTA 
    VALUES(MAX_ID,
           SYSDATE,
           MONTO * (:OLD.FECHA_HASTA - :OLD.FECHA_DESDE),
           v_mov_premio,
           CUENTA );
END INS_AFTER_UPD_PRICES;

祝你好运。

【讨论】:

  • 谢谢!如果不是你,我永远不会意识到。
猜你喜欢
  • 2015-07-09
  • 1970-01-01
  • 2021-03-29
  • 2021-02-13
  • 2017-06-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-01-02
相关资源
最近更新 更多