クエリを更新して、挿入前に重複するエントリが存在しないことを確認する必要があります。 MySQLではINSERT IGNOREを使用するだけでよいので、重複レコードが見つかった場合、挿入はスキップされますが、Oracleに相当するオプションを見つけることができないようです。助言がありますか?
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
テーブル(または任意の名前)を手動で作成する必要があります。
詳細はマニュアルをご覧ください
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.
私はそうは思いませんが、時間を節約するために、挿入を試みて不可避のエラーを無視することができます:
begin
insert into table_a( col1, col2, col3 )
values ( 1, 2, 3 );
exception when dup_val_on_index then
null;
end;
/
これは、主キーの重複または一意キーの制約によって具体的に発生した例外のみを無視します。それ以外はすべて通常どおり発生します。
これを実行したくない場合は、最初にテーブルから選択する必要がありますが、実際にはそれほど効率的ではありません。
別のバリアント
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
これは私のものではありませんが、sqlloaderを使用するときに非常に便利です。
テーブルを指すビューを作成します。
CREATE OR REPLACE VIEW test_view
AS SELECT * FROM test_tab
トリガーを作成します。
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;
ctlファイルで、代わりにビューに挿入します。
OPTIONS(ERRORS=0)
LOAD DATA
INFILE 'file_with_duplicates.csv'
INTO TABLE test_view
FIELDS TERMINATED BY ','
(id, field1)
簡単な解決策
insert into t1
select from t2
where not exists
(select 1 from t1 where t1.id= t2.id)
さらに別の「存在しない場所」-デュアルを使用したバリアント...
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');
重複をチェックするために必要なフィールドを持つインデックスを単に追加して、それが一意である必要があると言うのはどうですか?読み取りチェックを保存します。