0

考虑这张表:

表:订单列: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_ITEMS 这样的 ORDER 子表,其中必须更新类似的状态并审核信息)

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

如果我像 (A) 那样进行批量更新,我无法在订单级别进行审计。
如果我在 (B) 中的时间更新时选择单一订单,我将不得不循环 10,000 次——这可能很慢——但在这种情况下,我可以在订单级别进行审计。

还有其他方法吗?

4

3 回答 3

1

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

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

整洁高效。(对子查询进行排序是可选的:它可能会提高更新的性能,但关键是,我们可以将外部表视为常规表,并对其使用完整的 SELECT 语法。) 了解更多

其次,使用 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 值。 了解更多

如果将 for 的类型声明l_numsSQL 嵌套表对象,则可以在进一步的 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 子句并循环遍历每个子句要快得多。

请注意,更新通常是人类已知的最慢的批量操作。有一些方法可以加快它们的速度,但这些方法可能会涉及很多。但是,如果这是您经常想要做的事情并且性能成为一个症结,您应该阅读这篇 OraFAQ 文章

于 2013-02-17T04:56:19.623 回答
0

使用合并。首先将数据加载到一个名为 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

于 2013-02-16T19:21:02.570 回答
-1

我认为最好的方法是:

  • 首先将文件导入数据库
  • 然后在一个事务中执行少量 SQL UPDATE/INSERT 查询以更新status所有订单并创建审计记录。
于 2013-02-16T21:08:11.503 回答