我有一个表: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';
请帮帮我
答案 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;