首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >批量收集动态sql

批量收集动态sql
EN

Stack Overflow用户
提问于 2013-08-06 23:21:02
回答 1查看 4.3K关注 0票数 2

我必须编写一个动态sql游标,其中有几种生成select查询的可能性。因此,我选择了dynamic,并使用DBMS_SQL包动态创建游标并动态获取数据。

然而,结果集将是巨大的。大约11 80 (有240万条记录,select语句大约80个cols长,假设每列大约50Byte varchar )

因此,我不能立即打开光标。我想知道是否有一个特性可以让我从curosr中获取数据,同时保持curosr对1000条记录的开放(我将不得不动态地这样做)。

请找到附件中的代码,它只获取并打印我想要使用的列的值(一个示例案例)\

谢谢

代码语言:javascript
复制
---------------code sample--------------------------------------
--create or replace type TY_DIMDEAL AS TABLE OF VARCHAR2(50) ;
create or replace procedure         TEST_PROC (po_recordset out sys_refcursor)
as


  v_col_cnt   INTEGER;
  v_ind       NUMBER;
  rec_tab     DBMS_SQL.desc_tab;
  v_cursor    NUMBER;
  lvar_output number:=0;
  lvar_output1 varchar2(100);
  lvar_output3 varchar2(100);
  lvar_output2 varchar2(100);
  LVAR_TY_DIMDEAL TY_DIMDEAL;
 lvarcol varchar2(100);
begin
  --
  LVAR_TY_DIMDEAL := TY_DIMDEAL();
  lvar_output1 := '';

  v_cursor := dbms_sql.open_cursor;
  dbms_sql.parse(v_cursor, 'select to_char(Field1) , to_char(fiel2) , to_char(field3) from table,table2 ', dbms_sql.native);
  dbms_sql.describe_columns(v_cursor, v_col_cnt, rec_tab);
  FOR v_pos in 1..rec_tab.LAST LOOP

  LVAR_TY_DIMDEAL.EXTEND();
  DBMS_SQL.define_column( v_cursor, v_pos ,LVAR_TY_DIMDEAL(v_pos),20);
  END LOOP;
 -- DBMS_SQL.define_column( v_cursor, 1 ,lvar_output1,20);
  --DBMS_SQL.define_column( v_cursor, 2 ,lvar_output2,20);
 --DBMS_SQL.define_column( v_cursor, 3 ,lvar_output3,20);
  v_ind := dbms_sql.execute( v_cursor );

  LOOP
    v_ind := DBMS_SQL.FETCH_ROWS( v_cursor );
    EXIT WHEN v_ind = 0;
    lvar_output := lvar_output+1;
   dbms_output.put_line ('row number '||lvar_output)  ;

    FOR v_col_seq IN 1 .. rec_tab.COUNT LOOP  
    LVAR_TY_DIMDEAL(v_col_seq):= '';
     DBMS_SQL.COLUMN_VALUE( v_cursor, v_col_seq,LVAR_TY_DIMDEAL(v_col_seq));
    dbms_output.put_line (LVAR_TY_DIMDEAL(v_col_seq));

   END LOOP;



  END LOOP;

end TEST_PROC;
EN

回答 1

Stack Overflow用户

发布于 2013-08-08 02:36:05

在保持游标打开的同时,以合理大小的块从游标中获取数据是PL/SQL Best Practices的一种。

上面的文档(参见Code 38 item)概述了一种在运行时才知道选择列表的方法。基本上:

  1. 定义要将结果提取到的适当类型。让我们假设所有返回的列都是VARCHAR2类型的:

--在DECLARE Ty_FetchResults IS TABLE OF DBMS_SQL.VARCHAR2_TABLE中;在每次调用DBMS_SQL.FETCH_ROWS时,调用DBMS_SQL.DEFINE_ARRAY以使batch fetching.

  • Call DBMS_SQL.FETCH_ROWS能够从游标中提取1000行。

  • 调用DBMS_SQL.COLUMN_VALUE以在FOR循环中逐条记录地将所提取的数据复制到结果中。不要担心提取的记录数:如果有记录要处理,FOR循环将正确运行;如果结果数组为空,FOR循环将不会运行。当提取的记录数少于DBMS_SQL.CLOSE游标的预期size.

  • Remember时,

  • 将退出循环。

您的循环体应该如下所示:

代码语言:javascript
复制
LOOP
  FOR j IN 1..v_col_cnt LOOP
    DBMS_SQL.DEFINE_ARRAY(v_cursor, j, lvar_results(j), 1000, 1);
  END LOOP;

  v_ind := DBMS_SQL.FETCH_ROWS(v_cursor);

  FOR j IN 1..v_col_cnt LOOP
    lvar_results(j).DELETE;
    DBMS_SQL.COLUMN_VALUE(v_cursor, j, lvar_results(j));
  END LOOP;

  -- process the results, record by record
  FOR i IN 1..lvar_results(1).COUNT LOOP
    -- process a single record...
    -- your logic goes here
  END LOOP;

  EXIT WHEN lvar_results(1).COUNT < 1000;
END LOOP;

-- don't forget: DBMS_CLOSE(v_cursor);

另请参见Doing SQL from PL/SQL: Best and Worst Practices

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/18084244

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档