【问题标题】:How to catch a unique constraint error in a PL/SQL block?如何在 PL/SQL 块中捕获唯一约束错误?
【发布时间】:2010-10-01 04:58:16
【问题描述】:

假设我有一个 Oracle PL/SQL 块,它向表中插入一条记录,需要从唯一约束错误中恢复,如下所示:

begin
    insert into some_table ('some', 'values');
exception
    when ...
        update some_table set value = 'values' where key = 'some';
end;

是否可以用省略号替换某些内容以捕获唯一约束错误?

【问题讨论】:

  • 以这种方式使用异常有点慢,因为引发异常需要相当多的时间。尝试合并。
  • 同意。但请记住,这个例子只是许多可能的用例之一。问题实际上是“唯一约束错误的 id 是什么?”。这就是为什么我投了威廉的回答,但接受了里卡多的回答。
  • PL/SQL 代码中的异常不像托管或高级语言(C#、Java)那样昂贵。在数据库应用程序中,真正的“缓慢”是由数据库访问引起的,在这种情况下,PL/SQL 异常成本是微不足道的

标签: oracle plsql


【解决方案1】:
EXCEPTION
      WHEN DUP_VAL_ON_INDEX
      THEN
         UPDATE

【讨论】:

  • 如何写出导致问题的值?
【解决方案2】:

我相信你有你的理由,但以防万一......你还应该考虑使用“合并”查询:

begin
    merge into some_table st
    using (select 'some' name, 'values' value from dual) v
    on (st.name=v.name)
    when matched then update set st.value=v.value
    when not matched then insert (name, value) values (v.name, v.value);
end;

(将上述修改为在开始/结束块中;显然您也可以独立于程序运行它)。

【讨论】:

  • 这有助于这个特定的用例,但这只是一个例子。这个问题实际上是关于唯一约束错误的 id,所以我赞成这个答案,因为它确实很有帮助,但 Ricardo 的答案会被接受。
  • 里卡多的回答是正确的命名异常,但我认为威廉的建议从长远来看会帮助更多的人。
  • 在并行数据库会话中执行合并也可能导致在一个会话中违反唯一约束
【解决方案3】:

我怀疑你正在寻找的条件是DUP_VAL_ON_INDEX

EXCEPTION
    WHEN DUP_VAL_ON_INDEX THEN
        DBMS_OUTPUT.PUT_LINE('OH DEAR. I THINK IT IS TIME TO PANIC!')

【讨论】:

  • 如何写出导致问题的值?
  • 当异常被捕获时,运行一个新查询,只选择重复项并报告它们。
  • 您可以在运行查询之前这样做吗?
  • 我误导了你。您正在插入很多行。您只能在插入它们后选择它们。如果没有插入记录,则没有可供选择的内容。
【解决方案4】:

作为显式捕获和处理异常的替代方法,您可以通过在插入语句中包含 /*+ hint */ 来告诉 Oracle 捕获并自动忽略异常。这比显式捕获异常然后阐明应该如何处理它要快一些。它也更容易设置。缺点是您不会从 Oracle 获得任何关于捕获到异常的反馈。

这是一个示例,我们将从另一个表或内部查询中进行选择,并将结果插入一个名为 TABLE_NAME 的表中,该表对名为 IDX_COL_NAME 的列具有唯一约束。

INSERT /*+ ignore_row_on_dupkey_index(TABLE_NAME(IDX_COL_NAME)) */ 
INTO TABLE_NAME(
    INDEX_COL_NAME
  , col_1
  , col_2
  , col_3
  , ...
  , col_n)
SELECT 
    INDEX_COL_NAME
  , col_1
  , col_2
  , col_3
  , ...
  , col_n);

如果您的目标是捕获和处理(即打印或更新违反约束的行),这不是一个很好的解决方案。但是,如果您只是想抓住它并忽略违规行,那么这应该可以完成工作。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-07-05
    • 1970-01-01
    • 2018-11-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多