[英]Oracle : after insert into select, update the table
I need your advice to my below case. 对于以下情况,我需要您的建议。
I get data from maintable and insert into dataTable where rownum <= some value 我从主表获取数据并插入到dataTable中,其中rownum <=一些值
once all data already insert into datatable, i want this data in maintable will update the staus. 一旦所有数据都已经插入到数据表中,我希望主表中的数据将更新状态。
The problem is if the rownum more than 500k, it take about 10 minutes. 问题是,如果rownum超过500k,则大约需要10分钟。 This time there could be another request was pickup the same data.
这次可能还有另一个请求要提取相同的数据。 How i want to prevent this?
我要如何防止这种情况?
Below is my sql. 下面是我的sql。
insert into dataTable(id,num,status) select m.id,m.num,m.status from mainTable m where m.status = 'FREE' and rownum <= 100000;
update mainTable m set m.status = 'RESERVED' where m.num in (select d.num from dataTable where d.status = 'FREE');
I do some research, but i dont know whether i need to use the select for update
or merge
statement? 我做了一些研究,但是我不知道我是否需要使用
select for update
或merge
语句?
You can't use MERGE, as you can only insert into or update the target table. 您不能使用MERGE,因为您只能插入或更新目标表。 I would guess that the problem is either the selectivity of the column STATUS in
dataTable
or of the column NUM in mainTable
. 我想问题可能是
dataTable
中的STATUS列或mainTable
中的NUM列的mainTable
。
Either way, if you only want to update those rows in mainTable
that you've just inserted into mainTable
the simplest thing to do would be to remember what you've just inserted and update that. 无论哪种方式, 如果只想更新刚刚插入到
mainTable
中的mainTable
中的行,那么最简单的操作就是记住刚刚插入的行并进行更新。 A BULK COLLECT seems apposite. 批量收集似乎合适。
declare
cursor c_all is
select rowid as rid, id, num, status
from maintable
where status = 'FREE'
and rownum <= 100000;
type t__all is table of c_all%rowtype index by binary_integer;
t_all t__all;
begin
open c_all;
loop
fetch c_all bulk collect into t_all limit 10000;
forall i in t_all.first .. t_all.last
insert into datatable (id, num, status)
values (t_all(i).id, t_all(i).num, t_all(i.status));
forall i in t_all.first .. t_all.last
update maintable
set status = 'RESERVED'
where rowid t_all(i).rid;
end loop;
commit;
close c_all;
end;
/
This is not equivalent to your query, it assumes that maintable
is unique on NUM. 这并不等同于您的查询,它假定
maintable
在NUM上是唯一的。 If it unique on ID I would change the UPDATE to a MERGE (it's cleaner) and remove the ROWID column from the cursor: 如果它在ID上是唯一的,则将UPDATE更改为MERGE(更干净),然后从游标中删除ROWID列:
forall i in t_all.first .. t_all.last
merge into maintable m
using ( select t_all(i).num from dual ) d
on ( m.num = d.num )
when matched then
update
set m.status = 'RESERVED'
As I've written though, if the problem is the selectivity of the columns/indexing you need to post the explain plan, indexes etc. 如我所写,如果问题是列/索引的选择性,则需要发布解释计划,索引等。
I think that it is better that you use EXISTS
exchange of using in
in your update query, it is so faster: 我认为最好在更新查询中使用
EXISTS
交换使用in
这样会更快:
update mainTable m
set m.status = 'RESERVED'
where exists (select * from dataTable where m.num = d.num and d.status = 'FREE');
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.