Oracle Trigger - 表名是变异的,触发器/函数可能看不到它

时间:2015-05-26 15:21:32

标签: oracle triggers mutating-table

我正在使用以下Scenario(简化)的Oracle数据库:

Projects                      Params
-------------                 -----------
PROJ_ID     SCODE             PARAM_ID PARAM_TYPE PROJ_ID PARAM_VALUE
1000        123               5000       4614     1000    '00'
1001        124               5001       4610     1000    'Micro'
1002        123               5002       4614     1001    '02'
                              5003       4614     1002    '01'

这意味着,3个项目 - 项目1000有2个不同的参数,第二个和第三个项目各有一个参数。

现在我需要在projects表上编写一个Trigger,它会自动在params表中插入一个新行,该行具有给定SCODE类型为“4614”的参数的最大值+1。

INSERT INTO Projects VALUES (1003,123) 

...应触发事件

INSERT INTO Parameters VALUES (5004,4614,1003,'02')

现在我有两种可能性,两种都不起作用:

如果触发器被声明为“BEFORE”,我无法在Parameters表中插入,因为外键约束显示了一个错误,即尚未创建Project 1003。无法在触发器内执行提交。

如果触发器被声明为“AFTER”,则会出现错误

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

因为我正在访问现在触发的表格。

必须有解决此问题的方法。 任何帮助表示赞赏!

//修改

我的触发器:

CREATE OR REPLACE TRIGGER PROJ_ARI_TRIGGER
AFTER INSERT
ON PROJECTS
REFERENCING NEW AS NEW OLD AS OLD
FOR EACH ROW
DECLARE
v_param VARCHAR2(10);
BEGIN
      v_param := get_next_param_val(:new.SCODE);
      INSERT INTO Parameters(<<sequence>>,4614,:new.PROJ_ID,v_param);
END PROJ_ARI_TRIGGER;

函数get_next_param_val只是选择项目表并返回正确的参数值。

2 个答案:

答案 0 :(得分:0)

Darned变异表!包裹的时间。

CREATE OR REPLACE PACKAGE no_mutation_pkg
AS
   procedure set_val(pVal number);
   function get_val return number;
END;
/

CREATE OR REPLACE PACKAGE BODY no_mutation_pkg
AS
   g_val number;
   procedure set_val(pVal number)
   IS
     BEGIN
       g_val := pVAl;
   END;
   function get_val return number
   IS BEGIN
      return g_val;
   end;
   END;

然后创建一个BEFORE插入触发器,计算该值并使用set_val将其存储在包中,AFTER insert触发器使用GET_VAL检索该值并执行插入。

编辑:根据贾斯汀对重复的评论,你肯定需要考虑这一点。坦率地说,当你需要跳过这样的箍时,数据架构通常是可疑的

答案 1 :(得分:0)

我找到了解决问题的方法!

使用复合触发器,我可以先在SCODE中获取最大值并计算参数值(在每行之前)

然后在param表中插入值(在每行之后)

详细信息:Compound Trigger Example

谢谢@Bob Jarvis