批量更新表记录并进行审核

时间:2013-02-16 18:00:47

标签: sql database oracle batch-processing

考虑一下这个表:

表:ORDER 列:id,order_num,order_date,order_status

此表有100万条记录。我想将order_status更新为'5'的值,对于我将从输入文本文件中读取的一堆(大约10,000)order_num。

My SQL could be:
(A) update ORDER set order_status=5 where order_num in ('34343', '34454', '454545',...)
OR
(B) update ORDER set order_status=5 where order_num='34343' 

我可以多次循环此更新,直到我完成10,000次订单更新。 (另请注意,我有很少的ORDER子表,如ORDER_ITEMS,其中必须更新类似状态并审核信息)

我的问题是:
如何在单独的ORDER_AUDIT表中审核此更新:
Order_Num:34343 - 成功更新
Order_Num:34454 - 未找到订单
Order_Num:454545 - 成功更新
Order_Num:45457 - 订单未找到

如果按照(A)进行批量更新,我无法在订单级别进行审核 如果我按照(B)中的时间更新单一订单,我将需要循环10,000次 - 这可能相当慢 - 但在这种情况下我可以在订单级审核。

还有其他办法吗?

3 个答案:

答案 0 :(得分:1)

首先,在“输入文本文件”上构建一个外部表。这样你就可以运行一个简单的UPDATE语句:

update ORDER 
set order_status=5 
where order_num in ( select col1 from ext_table order by col1)

整洁有效。 (对子查询进行排序是可选的:它可以提高更新的性能,但关键是,我们可以像处理常规表一样处理外部表,并使用完整的SELECT语法。)Find out more

其次使用RETURNING子句捕获命中。

update ORDER 
set order_status=5 
where order_num in ( select col1 from ext_table order by col1)
returning order_num bulk collect into l_nums;
此上下文中的

l_nums是类型编号的PL / SQL集合。 RETURNING子句将仅为更新的行提供所有ORDER_NUM值。 Find out more

如果您将l_nums的类型声明为a SQL nested table object,则可以在其他SQL语句中将其用于审核:

 insert into order_audit 
 select 'Order_Num: '||to_char(t.column_value)||' - Updated Succesfully'    
 from table ( l_nums ) t
 /

 insert into order_audit 
 select 'Order_Num: '||to_char(col1)||' - Order Not Found'    
 from ext_table 
 minus 
 select * from table ( l_nums ) 
 /

绩效说明:

您没有说输入文本文件中有多少行匹配。也许你不知道(实际上重新阅读它不清楚10,000是文件中的行数还是匹配的行数)。 Pl / SQL集合使用私有会话内存,因此非常大的集合可以破坏PGA。但是,您应该能够处理一万个NUMBER个实例而不会蒙羞。

我的解决方案确实需要您两次读取外部表。这应该不是问题。它肯定会方式更快比动态组装一千个数字的一​​百个IN子句并循环遍历各个数字。

请注意,更新通常是人类已知的最慢的批量操作。有一些方法可以加速它们,但这些方法可以非常复杂。但是,如果这是你经常想要做的事情而性能成为一个棘手的问题你应该read this OraFAQ article

答案 1 :(得分:0)

使用MERGE。首先将数据加载到名为ORDER_UPD_TMP的临时表中,只有一个列id。您可以使用SQLDeveloper导入功能来完成此操作。然后使用MERGE来更新基表:

MERGE INTO ORDER b
USING (
  SELECT order_id
  FROM ORDER_UPD_TMP 
) e
ON (b.id = e.id)
WHEN MATCHED THEN
  UPDATE SET b.status = 5

当记录不匹配时,您还可以使用其他状态进行更新。查看文档以获取更多详细信息:

http://docs.oracle.com/cd/B28359_01/server.111/b28286/statements_9016.htm

答案 2 :(得分:-1)

我认为最好的方法是:

  • 首先将文件导入数据库
  • 然后在一个事务中执行一些SQL UPDATE / INSERT查询,以更新所有订单的status并创建审计记录。