para os dados a seguir, gostaria de poder deletar algumas linhas e inserir outras dando o resultado abaixo. Isso é possível com uma única instrução (por exemplo, com a merge
instrução)?
create table product(product_id integer primary key);
insert into product(product_id) values(1);
insert into product(product_id) values(2);
insert into product(product_id) values(3);
create table split( parent_id integer not null references product,
child_id integer not null references product,
primary key(parent_id, child_id) );
insert into split(parent_id, child_id) values(1,2);
insert into split(parent_id, child_id) values(1,3);
create table sale(sale_at date, product_id integer references product);
insert into sale(sale_at, product_id) values(sysdate, 1);
insert into sale(sale_at, product_id) values(sysdate, 1);
insert into sale(sale_at, product_id) values(sysdate, 1);
insert into sale(sale_at, product_id) values(sysdate, 2);
insert into sale(sale_at, product_id) values(sysdate, 2);
select sale_at, product_id from sale where product_id not in (select parent_id from split)
union all
select sale_at, child_id from sale join split on(parent_id=product_id);
/*
| SALE_AT | PRODUCT_ID |
--------------------------------------------
| June, 10 2013 15:18:22+0000 | 2 |
| June, 10 2013 15:18:22+0000 | 2 |
| June, 10 2013 15:18:22+0000 | 3 |
| June, 10 2013 15:18:22+0000 | 2 |
| June, 10 2013 15:18:22+0000 | 3 |
| June, 10 2013 15:18:22+0000 | 2 |
| June, 10 2013 15:18:22+0000 | 3 |
| June, 10 2013 15:18:22+0000 | 2 |
*/
( SQLFiddle )
----editar:
para esclarecer, o efeito que estou tentando obter com uma única merge
declaração é este:
insert into sale(sale_at, product_id)
select sale_at, child_id from sale join split on parent_id=product_id;
delete from sale where product_id in (select parent_id from split);
e o motivo pelo qual gostaria de uma solução de instrução única é evitar uma condição de corrida em que outra transação insere/confirma dados entre insert
e delete
na transação principal.
Você pode fazer isso de uma só vez, mais ou menos:
Isso excluirá as linhas da venda que estão presentes na divisão e as substituirá pelos produtos divididos apropriados.
Você também pode escrever:
Aqui a linha em venda será substituída (atualizada) por seu primeiro componente dividido e os componentes adicionais serão inseridos.