在forall中执行查询

时间:2017-10-03 12:35:45

标签: oracle plsql

我有一组存在查询的查询。 现在我想通过使用forall以下面显示的方式执行此操作:

open EX01_CURSOR;

LOOP
  FETCH EX01_CURSOR BULK COLLECT INTO Queries LIMIT 50000;
  EXIT WHEN Queries.COUNT = 0;
    FORALL i IN 1 .. Queries.count
    **execute immediate Queries(i).update_query;**
    commit;

END LOOP;

close EX01_CURSOR;

我想在forall块中执行我的查询。 我收到编译错误,如下所示:

  

没有BULK In-BIND的DML语句不能在FORALL

中使用
有人可以帮忙吗?

1 个答案:

答案 0 :(得分:0)

FORALL实际上不是LOOP或迭代器,而是BULK DML操作。它不会为集合中的每个条目(逐个条目)运行操作,而是对集合中的所有条目运行一个DML操作。您无法在Dynamic SQL中运行BULK,也无法进行迭代。要迭代并运行EXECUTE IMMEDIATE,您需要使用LOOP(或采用其他方法)。

这是一个例子。它仍使用BULK COLLECT来控制提交大小,但在Dynamic SQL中使用FOR LOOP。 (注意:执行此卷动态SQL效率不高。只是保留原始集合大小的示例)

设置测试数据:

CREATE TABLE TEST_TABLE (
  TEST_ID NUMBER
);
INSERT INTO TEST_TABLE SELECT LEVEL
                       FROM DUAL
                       CONNECT BY LEVEL <= 50001;

初始数据:

SELECT * FROM TEST_TABLE ORDER BY 1 DESC FETCH FIRST 5 ROWS ONLY;
TEST_ID  
50001           
50000           
49999           
49998           
49997     

然后运行块。这不会使用FORALL BULK DML。它使用FOR LOOP代替:

DECLARE

  CURSOR EX01_CURSOR IS (
    SELECT 'UPDATE TEST_TABLE SET TEST_TABLE.TEST_ID = TEST_TABLE.TEST_ID + 100000 WHERE TEST_TABLE.TEST_ID = ' ||
           TEST_TABLE.TEST_ID AS UPDATE_QUERY
    FROM TEST_TABLE);

  TYPE EX01_CUR_TYPE IS TABLE OF EX01_CURSOR%ROWTYPE;
  QUERIES EX01_CUR_TYPE;

BEGIN
  QUERIES := EX01_CUR_TYPE();

  OPEN EX01_CURSOR;

  LOOP
    FETCH EX01_CURSOR BULK COLLECT INTO QUERIES LIMIT 50000;
    EXIT WHEN QUERIES.COUNT = 0;

    FOR UPDATE_POINTER IN 1..QUERIES.COUNT
    LOOP
      EXECUTE IMMEDIATE QUERIES(UPDATE_POINTER).UPDATE_QUERY;
    END LOOP;
    COMMIT;

  END LOOP;

  CLOSE EX01_CURSOR;
END;
/

PL/SQL procedure successfully completed.

结果:

SELECT * FROM TEST_TABLE ORDER BY 1 DESC FETCH FIRST 5 ROWS ONLY;
TEST_ID  
150001   
150000   
149999   
149998   
149997