11

(DADSNBR, DAROLEID)一意の制約(一意のペア)を持つデータベーステーブルがあります。このテーブルに複数の値を同時に挿入するので、1つのクエリを使用してそれを実行したいと思います-これがより速い方法であると思います。したがって、私のクエリは次のとおりです。

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

ステートメント内には、データベースにすでに存在するエントリと重複するエントリがいくつかあるため、挿入全体が失敗し、どの行も挿入されません。

一意の制約が失敗した場合を無視して、個々のINSERTステートメントに分割せずに、一意の制約を挿入する方法はありますか?

編集:私はおそらくこれをとにかくやりたくないことに気づきましたが、それが可能かどうかについてはまだ興味があります。

4

2 に答える 2

12

Oracleでは、ステートメントは完全に成功するか、完全に失敗します(アトミックです)。ただし、場合によっては、エラーを発生させる代わりに、例外をログに記録する句を追加できます。

2番目の方法はすべて自動です。これがデモです(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

(thanks @Alex PooleLOG ERROR )で句を使用できますが、各テーブルの後に句を追加する必要があります。INSERT ALL

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.
于 2012-11-16T17:02:55.517 に答える
11

この状況を処理するには、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);
于 2012-11-16T17:24:24.757 に答える