【问题标题】:PLSQL Trigger may be causing INSERT INTO to fail silently?PLSQL 触发器可能导致 INSERT INTO 静默失败?
【发布时间】:2012-09-23 12:40:22
【问题描述】:

我有一个表,我正在尝试根据给定的值进行插入/更新。但是插入不适用于这个特定的表,但它适用于脚本运行的以前的表。

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

【问题讨论】:

    标签: oracle triggers plsql


    【解决方案1】:

    触发器不会修改表上的 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;
    

    【讨论】:

    • 谢谢,我删除了 sqldeveloper 中的异常,它告诉我违反了唯一约束。也就是说,通过触发器插入另一个表的数据是原因。我想我现在可以捕捉到那个异常并按照它执行。有没有更好的办法?
    • @user1636922 Merge 语句可能是其他更好的方法。
    【解决方案2】:

    您的附加信息告诉我们,您的触发器正在抛出 ORA-00001,这是一个唯一密钥违规。这是 DUP_VAL_ON_INDEX 异常处理的错误。所以看起来你的异常处理程序应该处理 COFFEE_TEA 上的关键违规行为,它也在吞噬你的触发器中的异常。凌乱。

    有两种可能的解决方案。一种是在触发代码中进行适当的错误处理。另一种是使用 MERGE 进行数据加载例程。

    我总是更喜欢 MERGE 作为执行 upserts 的机制,因为我不喜欢使用异常来处理合法的预期状态。 Find out more

    理想情况下,您应该两者都做。触发器应该是独立的代码:在与其表交互的例程上施加未处理的异常会破坏封装。

    【讨论】:

      猜你喜欢
      • 2021-03-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-12-20
      • 2011-09-29
      • 2010-11-22
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多