2013-07-17 78 views
10

有沒有辦法使用oracle merge插入和刪除而不是更新?Oracle sql合併插入並刪除但不更新

我有一個表格表示一組與另一個表中的單行相關的值。我可以通過全部刪除它們並添加新的集合,或者通過有選擇地刪除一些並添加其他集合來更改這組值,但如果可能,我有興趣將它作爲單個語句。

以下是更新的一個工作示例。爲了使這項工作,我不得不添加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。

回答

15

不,您不能刪除merge命令未更新的行。
下面是文檔: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使用相同的後WHERE子句因爲你是使用後刪除

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

我發現您可以將列設置爲自身:

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

這否定了對虛擬列的需求。

+0

as_value是否處於ON狀態?如果列處於ON狀態,這對我在11g中不起作用,即使更新將值設置爲自身,我也會得到「ON子句中引用的列無法更新」錯誤。 – Marquez

+0

這是正確的。根據oracle文檔,您無法更新屬於ON子句一部分的列。如果你仔細想想,這是有道理的。 但是您可以在更新中使用不同的非虛擬列;沒有嘗試過,我不知道刪除子句是否仍然會觸發相同的錯誤?例如。 SET b_value = b_value其中a_value不在('ace','afk')DELETE其中a_value不在('ace','afk')中。 – datico