PL / SQL触发器抛出MUTATING TABLE错误

时间:2015-06-25 15:22:02

标签: plsql triggers

我有这个触发器:

create or replace TRIGGER TR14_2 
BEFORE INSERT OR UPDATE OF CANTIDAD ON DISTRIBUCION 
FOR EACH ROW
DECLARE
  total_cars NUMBER;
  total_cars_potential NUMBER;
BEGIN
  SELECT sum(cantidad) into total_cars
    FROM DISTRIBUCION
    WHERE cifc = :NEW.cifc;
  total_cars_potential := total_cars + :NEW.cantidad;

  IF INSERTING THEN
    IF(total_cars_potential > 40) THEN
      raise_application_error(-20005, 'Dealer [' || :NEW.cifc || '] already has 40 cars stocked');
    END IF;
  END IF;

  IF UPDATING THEN
    IF(total_cars_potential - :OLD.cantidad > 40) THEN
      raise_application_error(-20006, 'That update of CANTIDAD makes the dealer exceeds the limit of 40 cars stocked');
    END IF;
  END IF;
END;

它得到一个变异表错误,我检查过是因为UPDATING代码块,INSERTING正常;但为什么?我该如何解决?

为了澄清,我希望每个经销商最多可以存放40辆汽车。因此,如果我使用cantidad("数量")向DISTRIBUCION(" distribution")添加一行将使经销商超过其最大库存,我将引发错误。 但是,如果我更新一个已经存放在数据库中的类型的汽车数量,并且我超过40辆汽车,我也想要抛出异常。

事实是,我没有在UPDATING块上看到mutatig表错误。

2 个答案:

答案 0 :(得分:0)

触发器无法更改已读取的表。这是变异表错误问题。

您可以在下面的链接中看到解决方案 Mutating table error

avoiding_mutating_table_error

答案 1 :(得分:0)

第1页:您获得变异表综合症的原因是您正在从触发器中更新的表中读取(选择总汽车数)。

第二:解决方案:我可能会创建两个触发器:一个for-each-row触发器,就像你收集包变量中更新的行一样

CREATE OR REPLACE PACKAGE PCK_TR14_2 IS
  TYPE changed_row IS RECORD (
        cantidad                DISTRIBUCION.cantidad%TYPE,
  );
  TYPE changed_row_table IS TABLE OF changed_rows INDEX BY binary_integer;
  changed_rows changed_row_table;
  cnt_changed_rows   BINARY_INTEGER   DEFAULT   1;
END PCK_TR14_2;
/

for-each-row触发器看起来像这样(现在是插入后的!)

create or replace TRIGGER TR14_2 
AFTER INSERT OR UPDATE OF CANTIDAD ON DISTRIBUCION 
FOR EACH ROW
DECLARE
BEGIN
  PCK_TR14_2.changed_rows(PCK_TR14_2.cnt_changed_rows).cantidad := :old.cantidad;
  PCK_TR14_2.cnt_changed_rows := PCK_TR14_2.cnt_changed_rows + 1;
END;
/

然后在after语句中触发器实现你的逻辑:

CREATE OR REPLACE TRIGGER TR14_2_S
AFTER INSERT OR UPDATE OF CANTIDAD ON DISTRIBUCION 
BEGIN
  FOR i IN PCK_TR14_2.changed_rows.FIRST..PCK_TR14_2.changed_rows.LAST LOOP
    -- YOUR LOGIC HERE
    null;
  END LOOP;
END;
/

访问" virtuell"中的候选人。表格根据需要(PCK_TR14_2.changed_rows(i).CANTIDAD)