web-dev-qa-db-ja.com

OracleはMySQLのINSERT IGNOREに相当しますか?

クエリを更新して、挿入前に重複するエントリが存在しないことを確認する必要があります。 MySQLではINSERT IGNOREを使用するだけでよいので、重複レコードが見つかった場合、挿入はスキップされますが、Oracleに相当するオプションを見つけることができないようです。助言がありますか?

23
Bad Programmer

MERGEステートメントを確認してください。これはあなたが望むことをするはずです-これを行うのはWHEN NOT MATCHED句です。

しかし、真のVALUES()句に対​​するOracleのサポートの欠如を考えると、固定値を持つ単一のレコードの構文はかなり不格好です。

MERGE INTO your_table yt
USING (
   SELECT 42 as the_pk_value, 
          'some_value' as some_column
   FROM dual
) t on (yt.pk = t.the_pke_value) 
WHEN NOT MATCHED THEN 
   INSERT (pk, the_column)
   VALUES (t.the_pk_value, t.some_column);

別のアプローチ(たとえば、別のテーブルから一括読み込みを行う場合)は、Oracleの「エラーロギング」機能を使用することです。ステートメントは次のようになります。

 INSERT INTO your_table (col1, col2, col3)
 SELECT c1, c2, c3
 FROM staging_table
 LOG ERRORS INTO errlog ('some comment') REJECT LIMIT UNLIMITED;

その後、エラーをスローしたすべての行がテーブルerrlogで利用可能になります。 DBMS_ERRLOG.CREATE_ERROR_LOGを使用して挿入を実行する前に、そのerrlogテーブル(または任意の名前)を手動で作成する必要があります。

詳細はマニュアルをご覧ください

29

11gを使用している場合は、ヒント IGNORE_ROW_ON_DUPKEY_INDEX を使用できます。

SQL> create table my_table(a number, constraint my_table_pk primary key (a));

Table created.

SQL> insert /*+ ignore_row_on_dupkey_index(my_table, my_table_pk) */
  2  into my_table
  3  select 1 from dual
  4  union all
  5  select 1 from dual;

1 row created.
24
Jon Heller

私はそうは思いませんが、時間を節約するために、挿入を試みて不可避のエラーを無視することができます:

begin

   insert into table_a( col1, col2, col3 )
   values ( 1, 2, 3 );

   exception when dup_val_on_index then 
      null;

end;
/

これは、主キーの重複または一意キーの制約によって具体的に発生した例外のみを無視します。それ以外はすべて通常どおり発生します。

これを実行したくない場合は、最初にテーブルから選択する必要がありますが、実際にはそれほど効率的ではありません。

8
Ben

別のバリアント

Insert into my_table (student_id, group_id)
select distinct p.studentid, g.groupid 
from person p, group g
where NOT EXISTS (select 1
                 from my_table a
                 where a.student_id = p.studentid
                 and a.group_id = g.groupid)

またはあなたができる

Insert into my_table (student_id, group_id)
select distinct p.studentid, g.groupid 
from person p, group g
MINUS
select student_id, group_id
from my_table 
4
rt.jar

これは私のものではありませんが、sqlloaderを使用するときに非常に便利です。

  1. テーブルを指すビューを作成します。

    CREATE OR REPLACE VIEW test_view
    AS SELECT * FROM test_tab
    
  2. トリガーを作成します。

    CREATE OR REPLACE TRIGGER test_trig
     INSTEAD OF INSERT ON test_view
     FOR EACH ROW
      BEGIN
       INSERT INTO test_tab VALUES
        (:NEW.id, :NEW.name);
      EXCEPTION
       WHEN DUP_VAL_ON_INDEX THEN NULL;
      END test_trig;
    
  3. ctlファイルで、代わりにビューに挿入します。

    OPTIONS(ERRORS=0)
    LOAD DATA
    INFILE 'file_with_duplicates.csv'
    INTO TABLE test_view
    FIELDS TERMINATED BY ','
    (id, field1)
    
1
vinnyman

簡単な解決策

insert into t1
  select from t2 
  where not exists 
    (select 1 from t1 where t1.id= t2.id)
1
knagaev

さらに別の「存在しない場所」-デュアルを使用したバリアント...

insert into t1(id, unique_name)
  select t1_seq.nextval, 'Franz-Xaver' from dual 
    where not exists (select 1 from t1 where unique_name = 'Franz-Xaver');
0
dev-null

重複をチェックするために必要なフィールドを持つインデックスを単に追加して、それが一意である必要があると言うのはどうですか?読み取りチェックを保存します。

0
spootdev