简体   繁体   English

在Oracle中批量收集

[英]bulk collect in oracle

How to query bulk collection? 如何查询批量收藏? If for example I have 如果我有

select name 
bulk collect into namesValues 
from table1

where namesValues is dbms_sql.varchar2_table . 其中namesValues是dbms_sql.varchar2_table

Now, I have another table XYZ which contains 现在,我有另一个包含XYZ的表格

 name   is_valid
  v
  h

I want to update is_valid to 'Y' if name is in table1 else 'N'. 如果name在table1中,则我想将is_valid更新为'Y',否则为'N'。 Table1 has 10 million rows. 表1有1000万行。 After bulk collecting I want to execute 批量收集后我想执行

update xyz 
set is_valid ='Y' 
where name in namesValue.

How to query namesValue? 如何查询namesValue? Or is there is another option. 或者还有另一种选择。 Table1 has no index. 表1没有索引。 please help. 请帮忙。

As Tom Kyte (Oracle Corp. Vice President) says: 正如Tom Kyte(甲骨文公司副总裁)所说:

My mantra, that I'll be sticking with thank you very much, is: 我非常感谢你的口头禅是:

You should do it in a single SQL statement if at all possible. 如果可能的话,您应该在单个SQL语句中执行此操作。

If you cannot do it in a single SQL Statement, then do it in PL/SQL. 如果您无法在单个SQL语句中执行此操作,请在PL / SQL中执行此操作。

If you cannot do it in PL/SQL, try a Java Stored Procedure. 如果您无法在PL / SQL中执行此操作,请尝试Java存储过程。

If you cannot do it in Java, do it in a C external procedure. 如果您不能在Java中执行此操作,请在C外部过程中执行此操作。

If you cannot do it in a C external routine, you might want to seriously think about why it is you need to do it… 如果你不能在C外部程序中做到这一点,你可能要认真思考为什么你需要这样做...

think in sets... 想一想......

learn all there is to learn about SQL... 学习所有有关SQL的知识......

You should perform your update in SQL if you can. 如果可以,您应该在SQL中执行更新。 If you need to add an index to do this then that might be preferable to looping through a collection populated with BULK COLLECT. 如果您需要添加索引来执行此操作,那么循环使用BULK COLLECT填充的集合可能更为可取。

If however, this is some sort of assignment.... You should specify it as such but here's how you would do it. 但是,如果这是某种分配....你应该这样指定它,但这是你将如何做到这一点。

I have assumed that your DB server does not have the capacity to hold 10 million records in memory so rather than BULK COLLECTing all 10 million records in one go I have put the BULK COLLECT into a loop to reduce your memory overheads. 我假设你的数据库服务器没有能力在内存中容纳1000万条记录,所以不是BULK一次性收集所有1000万条记录,而是将BULK COLLECT放入循环中以减少内存开销。 If this is not the case then you can omit the bulk collect loop. 如果不是这种情况,那么您可以省略批量收集循环。

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;
/

Depending upon your rollback segment sizes etc. you may want to issue interim commits within the bulk collect loop but be aware that you will not then be able to rollback these changes. 根据您的回滚段大小等,您可能希望在批量收集循环中发出临时提交,但请注意,您将无法回滚这些更改。 I deliberately haven't added any COMMITs to this so you can choose where to put them to suit your system. 我故意没有添加任何COMMIT,因此您可以选择将它们放在适合您的系统的位置。

You also might want to change the size of the c_bulk_limit constant depending upon the resources available to you. 您还可能希望根据可用资源更改c_bulk_limit常量的大小。

Your update will still cause you problems if the xyz table is large and there is no index on the name column. 如果xyz表很大并且名称列上没有索引,则更新仍会导致问题。

Hope it helps... 希望能帮助到你...

"Table1 has no index." “表1没有索引。”

Well there's your problem right there. 好吧那里有你的问题。 Why not? 为什么不? Put an index on TABLE1.NAME and use a normal SQL UPDATE to amend the data in XYZ. 在TABLE1.NAME上放置一个索引,并使用普通的SQL UPDATE来修改XYZ中的数据。

Trying to solve this problem with bulk collect is not the proper approach. 尝试使用批量收集来解决此问题并不是正确的方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM