Oracle INSERT INTO SELECT(...)DUP_VAL_ON_INDEX异常行为

时间:2013-02-01 15:30:03

标签: oracle exception

我有一个存储过程,如下所示:

BEGIN
  INSERT INTO result_table
  (SELECT (...) FROM query_table);
EXCEPTION
  WHEN DUP_VAL_ON_INDEX THEN
    NULL;
END;

我正在循环中将多个参数传递给SELECT语句,在某些情况下,某些值可能会重复,这就是为什么我必须捕获DUP_VAL_ON_INDEX异常。

我的问题是,如果SELECT语句返回更多行,并且* result_table *,f中只存在一行。离。

1 'A'
2 'B'
3 'C'

第一行(1'A')已经在表中,是否会插入其他不存在的行(上面的情况为第二行和第三行)?或者根本不会插入任何一个?

我担心它们都不会插入(我的测试用例部分证实了这一点)......如果是这样,我有什么选择来实现所需的行为?有没有一种很好的方法可以使用上面的结构插入不违反主键的行?

3 个答案:

答案 0 :(得分:2)

你是对的,如果一条记录违反约束,则不会插入任何记录。 我会做

INSERT INTO result_table
(SELECT (...) FROM query_table a WHERE NOT EXISTS
(SELECT NULL FROM result_table b WHERE b.b_unique_key = a.b_unique_key)
)

另一种选择是使用error logging

INSERT INTO result_table
SELECT ... FROM query_table 
LOG ERRORS INTO err$_dest ('INSERT') REJECT LIMIT UNLIMITED;

注意:您必须在运行此查询之前创建错误表。

答案 1 :(得分:2)

您可以使用MERGE声明。如果记录不存在则插入记录,如果记录已存在则不执行任何操作。

http://psoug.org/reference/merge.html

答案 2 :(得分:0)

如果你使用11g,那么你可以使用ignore_row_on_dupkey_index提示来抑制错误:

create table tab (id integer);

alter table tab add constraint tab_pk primary key (id);

insert into tab
  select rownum from dual connect by level <= 1;

1 rows inserted.
        ID
----------
         1 

SELECT * FROM tab;

insert into tab
  select rownum from dual connect by level <= 3;

SQL Error: ORA-00001: unique constraint (CAM_OWNER.TAB_PK) violated

insert /*+ ignore_row_on_dupkey_index(tab, tab_pk) */into tab
  select rownum from dual connect by level <= 3;

SELECT * FROM tab;

2 rows inserted.
        ID
----------
         1 
         2 
         3