在oracle触发器之前的sum值

时间:2014-06-30 11:18:11

标签: oracle triggers

我有一个表:Table1(field1,field2,field3)。 我想验证更新的值。 如果Sum(field1)group by field2> 10然后提出错误。

CREATE OR REPLACE TRIGGER HDB_TSGH_REVISE
   BEFORE UPDATE OF field1
   ON Table1 
   FOR EACH ROW
DECLARE
   v_sum_amt NUMBER := 0;
BEGIN
SELECT SUM(field1)
INTO v_sum_amt 
FROM Table1 
WHERE field2 = 'VND';

IF v_sum_amt  > 10 THEN
RAISE_APPLICATION_ERROR(-20000, 'ERROR');
END IF;

END;

Error 4091 at:
SELECT SUM(field1)
INTO v_sum_amt 
FROM Table1 
WHERE field2 = 'VND';

请帮帮我

2 个答案:

答案 0 :(得分:0)

这是由ORA-04091: table name is mutating, trigger/function may not see it

引起的

根据给出的建议,尝试使用AFTER UPDATE触发器而不是BEFORE UPDATE

由于您的情况是这样,如果出现错误,则不应更新该值,如果更新后触发器中出现错误,您可以重新更新为旧值。

您还可以考虑使用AUTONOMOUS TRANSACTION

答案 1 :(得分:0)

您无法从行级触发器中操作的同一个表中进行选择。

请勿使用自治事务来解决此错误。虽然自治事务会导致错误消失,但错误表明您的方法存在根本性错误,因此需要更改。

我会建议像:

CREATE OR REPLACE TRIGGER hdb_tsgh_revise
  FOR INSERT OR UPDATE OR DELETE ON table1
  COMPOUND TRIGGER

  -- Flag to indicate if VND total has been increased
  g_vnd_total_increased BOOLEAN;

BEFORE STATEMENT 
IS
BEGIN
  -- Reset VND total flag
  g_vnd_total_increased := FALSE;
END BEFORE STATEMENT; 

AFTER EACH ROW
IS
BEGIN
  -- If inserting VND record with positive value,
  -- Or updating to a VND record with a positive value,
  -- Or updating from a VND record with a negative value,
  -- Or updating a VND record to a larger value,
  -- Or deleting VND record with negative value;
  -- Then set the VND total flag
  IF (  (   INSERTING
        AND :new.field2 = 'VND'
        AND :new.field1 > 0)
     OR (   UPDATING
        AND (  (   nvl(:new.field2, '?') <> nvl(:old.field2, '?')
               AND (  (   :new.field2 = 'VND'
                      AND :new.field1 > 0)
                   OR (   :old.field2 = 'VND'
                      AND :old.filed1 < 0)))
            OR (   :new.field2 = 'VND'
               AND :old.field2 = 'VND'
               AND nvl(:new.field1, 0) > nvl(:old.field1, 0)) ) )
     OR (   DELETING
        AND :old.field2 = 'VND'
        AND :old.field1 < 0) )
  THEN
    g_vnd_total_increased := TRUE;
  END IF;
END AFTER EACH ROW;

AFTER STATEMENT
IS
  l_sum_field1 NUMBER;
BEGIN
  -- If VND total has been increased;
  -- Serialise the constraint so concurrent transactions do not affect each other
  -- Ensure VND total does not exceed allowed value
  IF g_vnd_total_increased THEN
    dbms_lock.request
      (id                => 12345  -- A unique id for this constraint
      ,lockmode          => dbms_lock.x_mode
      ,release_on_commit => TRUE);
    SELECT sum(field1)
    INTO l_sum_field1
    FROM table1
    WHERE field1 = 'VND';
    IF l_sum_field1 > 10 THEN
      raise_application_error(-20001, 'Field1 total for VND greater than 10 in Table1');
    END IF;
  END IF;
END AFTER STATEMENT;

END;