Oracle Bulk Collect and Update from cursor or user Update with Select 子查询

Posted

技术标签:

【中文标题】Oracle Bulk Collect and Update from cursor or user Update with Select 子查询【英文标题】:Oracle Bulk Collect and Update from cursor or user Update with Select subquery 【发布时间】:2012-08-31 11:01:03 【问题描述】:

我有 2 个选项可以根据选择查询的游标更新表。

假设我有这个选择查询:

select id1 from table1

我的更新查询是:

update table2 set value=1 where table2.id2 = table1.id1

现在有两个选项:

    为选择查询设置一个游标并批量获取它,然后在 for all 语句中触发更新查询。

    使用 select 子查询编写更新查询:

    update table2 set value=1 where table2.id2 in (select id1 from table1)

哪个更好?

Oracle 是在内部将 select 子查询转换为批量收集还是将其视为普通游标?

【问题讨论】:

【参考方案1】:

首先关于您的问题“Oracle 是否在内部将选择子查询转换为批量收集?” 不,优化器计算一个计划并以某种适当的方式从子查询中选择数据。不涉及批量收集。

对于您的问题“哪个更好?”。这要看情况。如果您可以制定一个查询,在一次运行中获取所有 table1.id1 并且 table2 有很多行,所以子选择是昂贵,那么我可能会使用批量收集。但请记住,根据数据量,您需要一些 PGA 来完成此操作。

但我可能会指出另一个 - 恕我直言,非常优雅 - 解决方案:

MERGE INTO table2
  USING (select id1 from table1)
   ON (id2 = id2)
  WHEN MATCHED THEN 
   UPDATE SET value=1
;

这通常比执行子查询更快,也比批量收集更快:一次在 table1 上运行,一次在 table2 上运行。 (根据您的需要添加where 子句)

【讨论】:

“首先你的问题是“Oracle 是否在内部将选择子查询转换为批量收集?”没有。老实说,这是不正确的。尝试使用 dbms_profiler FOR rec IN select ,您会看到隐式批量大约有 5 行:) @AlexanderTokarev:我不明白你的意思。 FOR rec IN select 显然会为 FOR 循环进行批量收集。问题在update table2 set value=1 where table2.id2 in (select id1 from table1) 上,不涉及批量收集。 PL/SQL FOR .. LOOP 不是子查询。 我明白你的意思。有点困惑 :) 错过了 SUBQUERY 词 :) 谢谢@GWu - 我会试试看。 @AlexanderTokarev - 我们是否有一些关于由 Oracle 自动将普通游标转换为批量收集 5 的文档。

以上是关于Oracle Bulk Collect and Update from cursor or user Update with Select 子查询的主要内容,如果未能解决你的问题,请参考以下文章

Oracle Bulk Collect and Update from cursor or user Update with Select 子查询

Oracle bulk collect into 的几种用法

重构 Oracle 存储过程以使用 BULK COLLECT

带有 BULK COLLECT 的 Oracle PL/SQL 6504

ORACLE批量绑定FORALL与BULK COLLECT

oracle plsql中同时记录类型、Collection和Bulk collect