【发布时间】:2015-05-26 15:21:31
【问题描述】:
我有一个具有以下场景(简化)的 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 表中插入一个新行,其中参数的最高值为 +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 只是选择项目表并返回正确的参数值。
【问题讨论】:
-
您可以更改外键,使其可延期;这样,在您提交之前不会对其进行检查。请记住,如果您进行批量更新,这可能会导致问题 - 在事务结束之前您不会收到错误。或者,不是直接插入到表中,而是通过存储过程来完成。这样,您就可以正确控制逻辑和流程,而无需做任何花哨的变通方法。
-
@Boneist 不幸的是,我无法更改数据库系统的约束。为什么将 INSERT 语句放入存储过程会有所帮助?我的触发器触发器的内容就像 v_new_param := calculate_param();插入参数值(....,new.proj_id,v_new_param)。
-
如果您要编辑问题以添加脚本来创建触发器会更好。
-
我不明白你试图描述的算法。您正在尝试获取
param_value值,对吗?为什么你会得到02的值?如果我们假设字符串值始终可以转换为数字,那不是当前数据的 max()+1 似乎是03。如果您正在执行 max()+1,您就会明白如果系统中允许多个用户,您将生成重复项,对吧?
标签: oracle triggers mutating-table