PLSQL触发器可能导致INSERT INTO无声地失败?

时间:2012-10-02 16:05:38

标签: oracle triggers plsql

我有一个表,我试图根据给出的值进行插入/更新。但是插件不适用于此特定表,但它适用于运行该脚本的先前表。

为了测试这个问题,我在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中删除了异常,它告诉我违反了一个唯一的约束。即通过触发器插入另一个表的数据是原因。

2 个答案:

答案 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;