立即执行中的批量收集限制

Posted

技术标签:

【中文标题】立即执行中的批量收集限制【英文标题】:BULK COLLECT LIMIT in EXECUTE IMMEDIATE 【发布时间】:2015-11-15 09:57:16 【问题描述】:

是否可以使用立即执行来限制批量收集?

我有以下脚本,但在使用 LIMIT 时出现错误。

declare
v_query varchar2(3000); 
begin 

v_query := 'select 1 from dual' -- this is just a sample query. 

execute immediate  v_query 
bulk collect into table1 --table type

end;

如果我的代码无法限制,是否有任何解决方法?

谢谢!

【问题讨论】:

您用“oracle 10g”标记了您的问题,但 LIMIT 子句在 10g 中不可用 【参考方案1】:

似乎 EXECUTE IMMEDIATE 语法不允许在批量收集子句中使用 LIMIThttp://docs.oracle.com/cd/E11882_01/appdev.112/e25519/executeimmediate_statement.htm#CJACGJJG

bulk_collect_into_clausehttp://docs.oracle.com/cd/E11882_01/appdev.112/e25519/returninginto_clause.htm#CJAIAGHJ


您可以将光标和 FETCH ..LIMIT 命令与 OPEN..FOR 命令一起使用, 这样:

DECLARE
  ....
  cur sys_refcursor;
BEGIN
  v_query := 'SELECT level AS x FROM dual CONNECT BY LEVEL <=10';
  OPEN cur FOR v_query;
  LOOP
     FETCH cur BULK COLLECT INTO collection LIMIT 3;
     EXIT WHEN collection.COUNT = 0;

     /* Process data from `collection` */

  END LOOP;
  CLOSE cur;
END;

例子:

DECLARE
  TYPE col_typ IS table of NUMBER;
  collection col_typ;
  v_query varchar2(3000); 
  cur sys_refcursor;
  i int := 0;
  x int;
BEGIN
  v_query := 'SELECT level AS x FROM dual CONNECT BY LEVEL <=10';

  OPEN cur FOR v_query;
  LOOP
     FETCH cur BULK COLLECT INTO collection LIMIT 3;
     EXIT WHEN collection.COUNT = 0;

     /* Process data from `collection` */
     i := i + 1;
     DBMS_OUTPUT.PUT_LINE('==== Batch nbr #' || i );
     FOR x IN 1 .. collection.COUNT LOOP
       DBMS_OUTPUT.PUT_LINE( collection( x ) );
     END LOOP;
  END LOOP;
  CLOSE cur;
END;
/

结果:

==== Batch nbr #1
1
2
3
==== Batch nbr #2
4
5
6
==== Batch nbr #3
7
8
9
==== Batch nbr #4
10

【讨论】:

非常感谢您。我仍然不明白为什么限制不适用于立即执行,但我会让我未来的自己弄清楚。不过,只有一个问题,对我的批量收集添加限制会改变我的脚本的性能吗?我添加 LIMIT 的主要目的是避免出现“快照太旧”的 oracle 错误,但我不确定哪个会更快。有限制或没有限制。【参考方案2】:

您可以使用DBMS_SQL 来执行此操作。但是,您必须检查游标变量。

DECLARE

  src_cur SYS_REFCURSOR;
  curid NUMBER;
  v_query varchar2(3000); 
  ret NUMBER;

BEGIN
  -- DBMS_SQL.OPEN_CURSOR
  curid := DBMS_SQL.OPEN_CURSOR;
  v_query := 'select 1 from dual';

  DBMS_SQL.PARSE(curid, v_query, DBMS_SQL.NATIVE);
  ret := DBMS_SQL.EXECUTE(curid);

  -- Switch from DBMS_SQL to native dynamic SQL
  src_cur := DBMS_SQL.TO_REFCURSOR(curid);

  -- Fetch with native dynamic SQL
  FETCH src_cur BULK COLLECT INTO ... LIMIT x;

  ...

【讨论】:

以上是关于立即执行中的批量收集限制的主要内容,如果未能解决你的问题,请参考以下文章

PLSQL - 批量收集的最大限制?

为啥批量收集到子句限制了 pl/sql 中嵌套表的大小

无法在立即执行中调用函数(存储在批量收集中)

在 discord.js 中的时间限制之前获取收集的消息

安全规则中的 Firebase 速率限制?

安全规则中的 Firebase 速率限制?