13

有没有办法使用 oracle 合并插入和删除但不更新?

我有一个表,表示与另一个表中的单行相关的一组值。我可以通过将它们全部删除并添加回新集,或者通过有选择地删除一些并添加其他值来更改值集,但如果可能的话,我有兴趣将其设为单个语句。

这是一个更新的工作示例。为了完成这项工作,我必须添加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。

4

2 回答 2

19

不,您不能删除尚未由合并命令更新的行。
这是文档:http ://docs.oracle.com/cd/B28359_01/server.111/b28286/statements_9016.htm

指定 DELETE where_clause 以在填充或更新表时清理表中的数据。受此子句影响的唯一行是目标表中由合并操作更新的那些行。DELETE WHERE 条件评估更新后的值,而不是由 UPDATE SET ... WHERE 条件评估的原始值。如果目标表的一行满足 DELETE 条件但不包含在 ON 子句定义的连接中,则不删除。目标表上定义的任何删除触发器都将为每次删除行激活。

这意味着,必须更新行。但是,您不需要更新所有行,在 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')
于 2013-07-17T20:57:44.893 回答
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')

这消除了对虚拟列的需要。

于 2014-02-20T23:46:44.750 回答