对于以下数据,我希望能够删除一些行并插入其他行,给出以下结果。这是否可以通过单个语句(例如merge
语句)来实现?
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 )
- - 编辑:
澄清一下,我试图用一个单一的merge
语句得到的效果是这样的:
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);
我想要一个单语句解决方案的原因是为了防止另一个事务在主事务insert
之间插入/提交数据的竞争条件。delete
你可以一口气完成,有点:
这将从销售中删除拆分中存在的行,并将其替换为相应的拆分产品。
你也可以这样写:
在这里,销售中的行将被其第一个拆分组件替换(更新),并且将插入其他组件。