我必须编写一个动态sql游标,其中有几种生成select查询的可能性。因此,我选择了dynamic,并使用DBMS_SQL包动态创建游标并动态获取数据。
然而,结果集将是巨大的。大约11 80 (有240万条记录,select语句大约80个cols长,假设每列大约50Byte varchar )
因此,我不能立即打开光标。我想知道是否有一个特性可以让我从curosr中获取数据,同时保持curosr对1000条记录的开放(我将不得不动态地这样做)。
请找到附件中的代码,它只获取并打印我想要使用的列的值(一个示例案例)\
谢谢
---------------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;
发布于 2013-08-08 02:36:05
在保持游标打开的同时,以合理大小的块从游标中获取数据是PL/SQL Best Practices的一种。
上面的文档(参见Code 38
item)概述了一种在运行时才知道选择列表的方法。基本上:
VARCHAR2
类型的:--在DECLARE Ty_FetchResults IS TABLE OF DBMS_SQL.VARCHAR2_TABLE中;在每次调用DBMS_SQL.FETCH_ROWS
时,调用DBMS_SQL.DEFINE_ARRAY
以使batch fetching.
DBMS_SQL.FETCH_ROWS
能够从游标中提取1000行。
DBMS_SQL.COLUMN_VALUE
以在FOR
循环中逐条记录地将所提取的数据复制到结果中。不要担心提取的记录数:如果有记录要处理,FOR
循环将正确运行;如果结果数组为空,FOR
循环将不会运行。当提取的记录数少于DBMS_SQL.CLOSE
游标的预期size.
您的循环体应该如下所示:
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);
https://stackoverflow.com/questions/18084244
复制相似问题