web-dev-qa-db-ja.com

挿入および削除するが更新ではないOracle SQLマージ

Oracleマージを使用して挿入と削除を行うが、更新はできない方法はありますか?

別のテーブルの1つの行に関連する一連の値を表すテーブルがあります。値のセットをすべて削除して新しいセットを追加するか、一部を選択的に削除してその他を追加することで、値のセットを変更できますが、可能であればそれを単一のステートメントにすることに興味があります。

以下は、更新を伴う実際の例です。これを機能させるには、dummyを追加して、on条件にない列を更新できるようにする必要がありました。更新するダミー列なしで削除と挿入のみを行う方法はありますか?

実際に更新されていなくても、on条件の列がupdate setリストに含まれていない可能性があります。

create table every_value ( the_value varchar2(32) );
create table paired_value ( the_id number, a_value varchar2(32) , dummy number default 0 );
-- the_id is a foreign_key to a row in another table

insert into every_value ( the_value ) values ( 'aaa' );
insert into every_value ( the_value ) values ( 'abc' );
insert into every_value ( the_value ) values ( 'ace' );
insert into every_value ( the_value ) values ( 'adg' );
insert into every_value ( the_value ) values ( 'aei' );
insert into every_value ( the_value ) values ( 'afk' );

-- pair ace and afk with id 3
merge into paired_value p using every_value e
on ( p.the_id = 3 and p.a_value = e.the_value )
when matched then update set dummy=dummy+1
delete where a_value not in ('ace','afk')
when not matched then insert (the_id,a_value)
values (3,e.the_value)
where e.the_value in ('ace','afk');

-- pair ace and aei with id 3
-- should remove afk, add aei, do nothing with ace
merge into paired_value p using every_value e
on ( p.the_id = 3 and p.a_value = e.the_value )
when matched then update set dummy = dummy+1
delete where a_value not in ('ace','aei')
when not matched then insert (the_id,a_value)
values (3,e.the_value)
where e.the_value in ('ace','aei');

-- pair aaa and adg with id 4
merge into paired_value p using every_value e
on ( p.the_id = 4 and p.a_value = e.the_value )
when matched then update set dummy = dummy+1
delete where a_value not in ('aaa','adg')
when not matched then insert (the_id,a_value)
values (4,e.the_value)
where e.the_value in ('aaa','adg');

select * from paired_value;

私はこれをOracle 10gで試しましたが、これで sqlfiddle 、Oracle 11gを試しました。

12
drawnonward

いいえ、マージコマンドで更新されていない行は削除できません。
ここにドキュメントがあります: http://docs.Oracle.com/cd/B28359_01/server.111/b28286/statements_9016.htm

DELETE where_clauseを指定して、データの移入または更新中に表のデータをクリーンアップします。 この句の影響を受ける行は、マージ操作によって更新される宛先テーブルの行のみです。 DELETE WHERE条件は、UPDATE SET ... WHERE条件によって評価された元の値ではなく、更新された値を評価します。宛先テーブルの行がDELETE条件を満たすが、ON句で定義された結合に含まれていない場合、その行は削除されません。ターゲット表で定義された削除トリガーは、行が削除されるたびにアクティブになります。

つまり、行は更新する必要があります。 Hovewer、すべての行を更新する必要はありません。UPDATEの後は、DELETEの後と同じWHERE句を使用します。

when matched then update set dummy=dummy
    where a_value not in ('ace','afk')
delete 
    where a_value not in ('ace','afk')
16
krokodilko

列をそれ自体に設定できることがわかりました:

MERGE ...
WHEN MATCHED THEN 
   UPDATE SET a_value = a_value WHERE a_value not in ('ace','afk')
   DELETE WHERE a_value not in ('ace','afk')

これにより、ダミー列の必要性がなくなります。

1
datico