2013-07-17 16 views
10

Oracleのマージを使用して挿入および削除を行いますが、更新はできませんか?Oracle sqlのマージで挿入および削除が行われますが、更新はされません

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

ここには更新のある実例があります。この作業を行うために、dummyを追加して、onの条件にない列を更新できるようにしなければなりませんでした。更新するためにダミー列を削除せずに挿入するしかありませんか?

の条件の列は、実際には更新されていなくてもよい。

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; 

私は、このsqlfiddleでは、Oracle 11gのOracle 10gのでこれをしようとしたしています。

答えて

15

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

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

つまり、行は、を更新する必要があります。

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') 

:あなたが後に使用しているよう句は

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

ダミー列を持つよりも良い方法はないと確信していましたが、ダミー列を追加するつもりはありません。しかたがない。 – drawnonward

1

をDELETE WHERE Hovewer、あなたは私はあなたが自分自身に列を設定することができます発見したUPDATEが同じを使用した後、すべての行を更新する必要はありませんこれは、ダミー列の必要性を否定します。

+0

あなたのオン状態でas_valueはありますか?これは11gで私のために働いていませんでした。カラムがON状態にある場合、更新が値を自分自身に設定していても「ON句で参照されるカラムは更新できません」というエラーが発生します。 – Marquez

+0

それは正しいです。 oracleのドキュメントでは、ON句の一部である列を更新できません。あなたがそれについて考えるなら、意味があります。 しかし、アップデートでは別のダミー以外の列を使うことができます。それを試すことなく、私は削除句がまだ同じエラーを引き起こすかどうかわからないのですか?例えば。 SET b_value = b_valueここでa_valueは( 'ace'、 'afk')ではありません。a_valueは( 'ace'、 'afk')にはありません。 – datico

関連する問題