【问题标题】:Mutating table error thrown from stored procedure fired by an after insert trigger插入后触发器触发的存储过程引发的变异表错误
【发布时间】:2015-02-05 01:58:54
【问题描述】:

每当数据插入表时,我需要通过“插入后”触发器调用存储过程,但我遇到“错误 ORA-04091:表 TEST.EMP 正在变异,触发器/函数可能看不到它”。我了解此错误背后的原因,但是如何在不影响程序的情况下通过复合触发器克服此错误?

create TABLE emp(
id NUMBER(4),
emp_name VARCHAR2(30),
dept_name VARCHAR2(10));

create or replace PROCEDURE emp_count(dept_name_v emp.dept_name%TYPE) as
DECLARE
dept_emp_count NUMBER(4) := 0;
BEGIN
SELECT count(*) INTO dept_emp_count FROM emp WHERE dept_name = dept_name_v;
UPDATE dept_stat SET d_emp_count = dept_emp_count WHERE dept_name =  dept_name_v;
END;

create or replace TRIGGER dept
AFTER INSERT ON emp
FOR EACH ROW
BEGIN
emp_count(:NEW.dept_name);
END;

【问题讨论】:

  • 您不要在生产系统中使用DBMS_OUTPUT。那么为什么你需要什么都不做的程序呢?
  • 调整程序以回答您的问题。给定的场景是一个更容易理解的样本。

标签: oracle plsql database-trigger mutating-table


【解决方案1】:

文档中有一个示例如何创建复合触发器:
http://docs.oracle.com/cd/B28359_01/appdev.111/b28370/triggers.htm#CHDFEBFJ

只需更改此示例中的一些标识符和声明,您将获得针对您的案例的触发器:

CREATE OR REPLACE TRIGGER some_trigger
 FOR INSERT ON  emp
COMPOUND TRIGGER

TYPE dept_names_t IS TABLE OF emp.dept_name%TYPE INDEX BY SIMPLE_INTEGER;
  dept_names  dept_names_t;
  idx       SIMPLE_INTEGER := 0;

 -- AFTER EACH ROW Section:

  AFTER EACH ROW IS
  BEGIN
    idx := idx + 1;
    dept_names(idx) := :NEW.dept_name;
  END AFTER EACH ROW;

AFTER STATEMENT IS
  BEGIN
   FOR  j IN 1..idx
   LOOP
     emp_count(dept_names(j));
   END LOOP;
END AFTER STATEMENT;
END; 
/

【讨论】:

    猜你喜欢
    • 2016-06-17
    • 2011-06-20
    • 1970-01-01
    • 2019-09-15
    • 1970-01-01
    • 1970-01-01
    • 2013-07-17
    • 1970-01-01
    • 2016-04-20
    相关资源
    最近更新 更多