0

我有一个具有以下场景(简化)的 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 个不同的参数,第二个和第三个项目各有一个参数。

现在我需要在项目表上编写一个触发器,它会自动在参数表中插入一个新行,其中参数的最高值为 +1,类型为“4614”,具有给定的 SCODE。

INSERT INTO Projects VALUES (1003,123) 

...应该触发事件

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

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

如果触发器声明为“BEFORE”,我无法在参数表中插入,因为外键约束向我显示一个错误,即 Project 1003 尚未创建。不可能在触发器内执行 Commit。

如果触发器被声明为“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 只是选择项目表并返回正确的参数值。

4

2 回答 2

0

该死的变异表!是时候打包了。

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 插入触发器使用 GET_VAL 检索该值并执行插入。

编辑:根据贾斯汀对重复项的评论,您肯定需要考虑这一点。坦率地说,当您需要跳过这些障碍时,通常会怀疑数据架构

于 2015-05-26T16:18:23.403 回答
0

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

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

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

详细信息:复合触发器示例

谢谢@鲍勃贾维斯

于 2015-05-27T09:41:07.877 回答