Oracle sql merge для вставки и удаления, но не обновления

Есть ли способ использовать слияние оракула для вставки и удаления, но не обновления?

У меня есть таблица, представляющая набор значений, связанных с одной строкой в ​​другой таблице. Я мог бы изменить набор значений, удалив их все и добавив обратно новый набор, или выборочно удалив некоторые и добавив другие, но я заинтересован в том, чтобы сделать его одним выражением, если это возможно.

Вот рабочий пример с обновлением. Чтобы выполнить эту работу, мне пришлось добавить 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.

Ответ 1

Нет, вы не можете удалить строки, которые не были обновлены командой слияния.
Вот документация: 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, которое вы используете после DELETE

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

Ответ 2

Я обнаружил, что вы можете установить столбец сам по себе:

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

Это отрицает необходимость использования фиктивного столбца.