Oracle'INSERT ALL'忽略重复项

Mac*_*ath 8 oracle insert duplicates unique-constraint

我有一个数据库表,它有一个唯一的约束(唯一(DADSNBR, DAROLEID)对).我将同时在这个表中插入多个值,所以我想使用一个查询完成它 - 我假设这将是更快的方式.我的查询是这样的:

INSERT ALL
    INTO ACCESS (DADSNBR, DAROLEID) VALUES (68, 1)
    INTO ACCESS (DADSNBR, DAROLEID) VALUES (68, 2)
    INTO ACCESS (DADSNBR, DAROLEID) VALUES (68, 3)
    INTO ACCESS (DADSNBR, DAROLEID) VALUES (68, 4)
SELECT 1 FROM DUAL
Run Code Online (Sandbox Code Playgroud)

由于语句中的某些条目与数据库中已存在的条目重复,因此整个插入失败并且未插入任何行.

有没有办法忽略唯一约束失败的情况,只需插入唯一的那些,而不必将其拆分成单独的INSERT语句?

编辑:我意识到我可能不想这样做,但我仍然很好奇它是否可能.

Vin*_*rat 12

在Oracle中,语句要么完全成功要么完全失败(它们是原子的).但是,您可以在某些情况下添加子句来记录异常而不是引发错误:

第二种方法都是自动的,这是一个演示(使用11gR2):

SQL> CREATE TABLE test (pk1 NUMBER,
  2                     pk2 NUMBER,
  3                     CONSTRAINT pk_test PRIMARY KEY (pk1, pk2));

Table created.

SQL> /* Statement fails because of duplicate */
SQL> INSERT into test (SELECT 1, 1 FROM dual CONNECT BY LEVEL <= 2);

ERROR at line 1:
ORA-00001: unique constraint (VNZ.PK_TEST) violated

SQL> BEGIN dbms_errlog.create_error_log('TEST'); END;
  2  /

PL/SQL procedure successfully completed.

SQL> /* Statement succeeds and the error will be logged */
SQL> INSERT into test (SELECT 1, 1 FROM dual CONNECT BY LEVEL <= 2)
  2   LOG ERRORS REJECT LIMIT UNLIMITED;

1 row(s) inserted.

SQL> select ORA_ERR_MESG$, pk1, pk2 from err$_test;

ORA_ERR_MESG$                                       PK1 PK2
--------------------------------------------------- --- ---
ORA-00001: unique constraint (VNZ.PK_TEST) violated   1   1
Run Code Online (Sandbox Code Playgroud)

您可以使用该LOG ERROR子句INSERT ALL(感谢@Alex Poole),但您必须在每个表之后添加该子句:

SQL> INSERT ALL
  2   INTO test VALUES (1, 1) LOG ERRORS REJECT LIMIT UNLIMITED
  3   INTO test VALUES (1, 1) LOG ERRORS REJECT LIMIT UNLIMITED
  4  (SELECT * FROM dual);

0 row(s) inserted.
Run Code Online (Sandbox Code Playgroud)

  • 它与`INSERT ALL`一起使用,但你需要在每个'INTO ...'之后放一个`LOG ERRORS`子句,如[docs](http://docs.oracle.com/)中所示. CD/E11882_01/server.112/e26088/statements_9014.htm#i2121682).所以在这种情况下``INSERT ALL INTO test VALUES(1,1)LOG ERRORS REJECT LIMIT UNITIMIT INTO test VALUES(1,1)LOG ERRORS REJECT LIMIT UNLIMITED SELECT*FROM dual`.这可能是有道理的,因为`INTO可能适用于不同的桌子. (5认同)

a_h*_*ame 10

使用MERGE语句来处理这种情况:

merge into "ACCESS" a
using
( 
   select 68 as DADSNBR,1 as DAROLEID from dual union all
   select 68,2 from dual union all
   select 68,3 from dual union all
   select 68,4 from dual
) t 
on (t.DADSNBR = a.DADSNBR and t.DAROLEID = a.DAROLEID)
when not matched then 
  insert (DADSNBR, DAROLEID)
  values (t.DADSNBR, t.DAROLEID);
Run Code Online (Sandbox Code Playgroud)

  • @Maccath - [`union all`](http://docs.oracle.com/cd/E11882_01/server.112/e26088/operators005.htm#sthref833)结合了几个`select`语句 - 本例中有四个,如你原来的问题 - 在一个结果集中.你的版本有一个尾随的'union all`; 不应该出现在最后一个`select`子语句之后. (2认同)