2015-05-26 30 views
0

我有以下方案(简化的)Oracle数据库: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个不同的参数第二个和第三个项目各有一个参数。

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

INSERT INTO Projects VALUES (1003,123) 

...应该触发事件

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

现在我有2种可能性,这两个不工作:

如果触发被声明为“之前”,我不能插入在参数表中,因为外键约束表明我还没有创建Project 1003的错误。在触发器内部进行提交是不可能的。

如果触发被声明为“后”,我得到一个错误

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只是没有选择的项目表,并返回正确的参数值。

+1

你可以改变外键,以便它可以推迟;这样,直到你提交之后才会被检查。请记住,如果您正在进行批量更新,这可能会导致问题 - 直到交易结束时才会发生错误。或者,不要直接插入表中,而要通过存储过程来完成。这样,您就可以正确控制逻辑和流程,而无需执行任何花哨的解决方法。 – Boneist

+0

@Boneist不幸的是我不能改变数据库系统的约束。为什么要将INSERT语句放入存储过程帮助?我的触发器触发器的内容就像v_new_param:= calculate_param();插入参数值(....,new.proj_id,v_new_param)。 –

+0

如果您要编辑问题以添加脚本以创建触发器,那将会更好。 – Boneist

回答

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 INSERT触发器与set_val计算包的价值,并将其存储和AFTER INSERT触发器检索与GET_VAL值并执行插入。

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

+0

'后'触发器需要是'语句'级别。 – GriffeyDog

+0

很好。谢谢!我今天正在打字,因为我离开了办公室。 –

0

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

使用化合物触发,我可以先获得在SCODE最大值和(每行之前)计算PARAM值

,然后将每个后插入在参数表中的值(有行)

详情:Compound Trigger Example

谢谢@Bob贾维斯

+0

根据上面的评论,如果这是一个多用户系统,您可能需要测试以确保在两个人执行类似插入操作时不会得到重复项。例如对于上面的数据集有一个人用scode123插入项目1003,然后用scode123插入另一个插入项目1004,然后两者都进行提交。 –

相关问题