在Oracle中批量收集

fac*_*ook 2 oracle plsql oracle11g

如何查询批量收藏?如果我有

select name 
bulk collect into namesValues 
from table1
Run Code Online (Sandbox Code Playgroud)

其中namesValues是dbms_sql.varchar2_table.

现在,我有另一个包含XYZ的表格

 name   is_valid
  v
  h
Run Code Online (Sandbox Code Playgroud)

如果name在table1中,则我想将is_valid更新为'Y',否则为'N'.表1有1000万行.批量收集后我想执行

update xyz 
set is_valid ='Y' 
where name in namesValue.
Run Code Online (Sandbox Code Playgroud)

如何查询namesValue?或者还有另一种选择.表1没有索引.请帮忙.

Oll*_*lie 5

正如Tom Kyte(甲骨文公司副总裁)所说:

我非常感谢你的口头禅是:

如果可能的话,您应该在单个SQL语句中执行此操作.

如果您无法在单个SQL语句中执行此操作,请在PL/SQL中执行此操作.

如果您无法在PL/SQL中执行此操作,请尝试Java存储过程.

如果您不能在Java中执行此操作,请在C外部过程中执行此操作.

如果你不能在C外部程序中做到这一点,你可能需要认真思考为什么你需要这样做...

想一想......

学习所有有关SQL的知识......

如果可以,您应该在SQL中执行更新.如果您需要添加索引来执行此操作,那么循环使用BULK COLLECT填充的集合可能更为可取.

但是,如果这是某种分配....你应该这样指定它,但这是你将如何做到这一点.

我假设你的数据库服务器没有能力在内存中容纳1000万条记录,所以不是BULK一次性收集所有1000万条记录,而是将BULK COLLECT放入循环中以减少内存开销.如果不是这种情况,那么您可以省略批量收集循环.

DECLARE
   c_bulk_limit CONSTANT PLS_INTEGER := 500000;
   --
   CURSOR names_cur
   IS
      SELECT name
        FROM table1;
   --
   TYPE namesValuesType IS TABLE OF table1.name%TYPE
        INDEX BY PLS_INTEGER;
   namesValues namesValuesType;
BEGIN

   -- Populate the collection
   OPEN name_cur;
   LOOP
      -- Fetch the records in a loop limiting them 
      -- to the c_bulk_limit amount at a time
      FETCH name_cur BULK COLLECT INTO namesValues
      LIMIT c_bulk_limit;

      -- Process the records in your collection
      FORALL x IN INDICES OF namesValues
         UPDATE xyz
            SET is_valid ='Y'
          WHERE name = namesValue(x)
            AND is_valid != 'Y';  

      -- Set up loop exit criteria
      EXIT WHEN namesValues.COUNT < c_bulk_limit;
   END LOOP;
   CLOSE name_cur;

   -- You want to update all remaining rows to 'N'
   UPDATE xyz
      SET is_valid ='N'
    WHERE is_valid IS NULL; 

EXCEPTION
   WHEN others
   THEN
      IF name_cur%ISOPEN 
      THEN
         CLOSE name_cur;
      END IF;
      -- Re-raise the exception;
      RAISE;
END;
/
Run Code Online (Sandbox Code Playgroud)

根据您的回滚段大小等,您可能希望在批量收集循环中发出临时提交,但请注意,您将无法回滚这些更改.我故意没有为此添加任何COMMIT,因此您可以选择将它们放在适合您的系统的位置.

您还可能希望根据可用资源更改c_bulk_limit常量的大小.

如果xyz表很大并且名称列上没有索引,则更新仍会导致问题.

希望能帮助到你...