我有一个表,我试图根据给出的值进行插入/更新。但是插件不适用于此特定表,但它适用于运行该脚本的先前表。
为了测试这个问题,我在oracle的sqldeveloper中添加了一些匿名块,根据是否存在密钥,它会插入或更新。更新似乎工作正常,但是当插入新行时,不会插入任何内容。
如果我有这张桌子:
COFFEE_ID TEA_ID NAME
11 100 combo 1
12 101 combo 2
13 102 combo 3
执行此操作不会插入任何内容,而是转到下一个匿名块:
begin
insert into COFFEE_TEA(COFFEE_ID, TEA_ID, NAME) values (14, 103, 'combo 4');
exception when dup_val_on_index then
update ....
end;
....
我怀疑它与此表上的触发器有关。它是BEFORE EACH ROW
触发器类型,它会将数据插入到其他表中。触发器中没有异常处理,所以我猜它必须失败但不报告它(当我运行脚本时不会出现在sqldeveloper中)。
我的两个问题是,
当触发器运行时,如果它试图插入到另一个表中的ID已经存在,会发生什么?看起来它默默地失败了?
我该如何解决这个问题?我不确定我是否可以更改触发器代码本身,但是可以捕获我的匿名块内的错误(假设它实际上是导致问题的触发器)。如果是这样,如果它无声地失败,我怎么知道要捕获的异常?
我在sqldeveloper中删除了异常,它告诉我违反了一个唯一的约束。即通过触发器插入另一个表的数据是原因。
答案 0 :(得分:3)
您的其他信息告诉我们您的触发器是ORA-00001,这是一种独特的密钥违规行为。这是DUP_VAL_ON_INDEX异常处理的错误。所以看起来你应该处理COFFEE_TEA上的密钥违规的异常处理程序也吞噬了触发器的异常。凌乱。
有两种可能的解决方案。一种是在触发代码中加入适当的错误处理。另一种是使用MERGE进行数据加载例程。
我总是喜欢MERGE作为执行upserts的机制,因为我不喜欢使用异常来处理合法的期望状态。 Find out more。
理想情况下,你应该做到这两点。触发器应该是自包含的代码:在与其表交互的例程上强加未处理的异常会破坏封装。
答案 1 :(得分:0)
触发器不会修改表上的DML进程。如果COFFEE_TEA
是表,则删除异常块,插入将成功或失败并显示错误。
换句话说,如果COFFEE_TEA
是一个表,则以下脚本永远不会输出0:
BEGIN
INSERT INTO coffee_tea(COFFEE_ID, TEA_ID, NAME) values (14, 103, 'combo 4');
dbms_output.put_line(sql%rowcount);
END;