Oracle 将动态结果集提取到游标中的最佳方法

Oracle 将动态结果集提取到游标中的最佳方法,oracle,plsql,Oracle,Plsql,我有一个报告函数,它接受SQL查询并在其上生成一些聚合和转换。所有查询都返回具有以下结构的列:ID、COL1、COl2、COL3。。。。COL25 该函数将结果提取到游标中以进行处理,并将行存储在变量中,如下所示: OPEN C1 FOR V_SQL; LOOP CASE COLUMN_COUNT WHEN 3 THEN FETCH C1 INTO ROW.C1,ROW.C2,

我有一个报告函数,它接受SQL查询并在其上生成一些聚合和转换。所有查询都返回具有以下结构的列:ID、COL1、COl2、COL3。。。。COL25

该函数将结果提取到游标中以进行处理,并将行存储在变量中,如下所示:

    OPEN C1 FOR V_SQL;
        LOOP
            CASE COLUMN_COUNT
                WHEN 3 THEN
                    FETCH C1 INTO ROW.C1,ROW.C2,ROW.C3;
                WHEN 4 THEN
                    FETCH C1 INTO ROW.C1,ROW.C2,ROW.C3,ROW.C4;
                WHEN 5 THEN
                    FETCH C1 INTO ROW.C1,ROW.C2,ROW.C3,ROW.C4,ROW.C5;
                ... (until 29 columns)

详情如下:

    OPEN C1 FOR V_SQL;
        LOOP
            CASE COLUMN_COUNT
                WHEN 3 THEN
                    FETCH C1 INTO ROW.C1,ROW.C2,ROW.C3;
                WHEN 4 THEN
                    FETCH C1 INTO ROW.C1,ROW.C2,ROW.C3,ROW.C4;
                WHEN 5 THEN
                    FETCH C1 INTO ROW.C1,ROW.C2,ROW.C3,ROW.C4,ROW.C5;
                ... (until 29 columns)


现在,我需要支持多达100个列。这将使代码非常大。如何像数组一样以动态方式实现这一点?

此过程接收SQL查询文本(来自安全源-请注意,否则您应该对恶意代码执行一些基本检查)以及许多要获取的列

该过程解析查询,动态定义所需计数中的列,并获取行以生成DBMS_输出-您应该了解您的用例

您可以省略
col\u cnt
参数,并使用
DBMS\u SQL从游标获取值。描述列
,但这需要额外打开/关闭游标

CREATE OR REPLACE PROCEDURE ftch ( 
     sql_txt      IN VARCHAR2, 
     col_cnt      IN NUMBER) IS 

     type array_vc_t is varray(100) of varchar2(30);     
     id                 NUMBER; 
     cols               array_vc_t := array_vc_t(); 
     source_cursor      INTEGER;  
     ignore             INTEGER; 
  BEGIN 

     source_cursor := dbms_sql.open_cursor; 
     DBMS_SQL.PARSE(source_cursor,sql_txt, DBMS_SQL.NATIVE); 

     DBMS_SQL.DEFINE_COLUMN(source_cursor, 1, id); 
     for i in 1..col_cnt loop
          cols.extend();     
          DBMS_SQL.DEFINE_COLUMN(source_cursor, i+1, cols(i), 30); 
     end loop; 
     ignore := DBMS_SQL.EXECUTE(source_cursor); 

     LOOP 
       IF DBMS_SQL.FETCH_ROWS(source_cursor)>0 THEN 

         DBMS_SQL.COLUMN_VALUE(source_cursor, 1, id); 
         for i in 1..col_cnt loop
             DBMS_SQL.COLUMN_VALUE(source_cursor, i+1, cols(i)); 
         end loop;
         dbms_output.put_line('id= '|| id );
         for i in 1..col_cnt loop
             dbms_output.put_line('        i='|| i || ' col = '|| cols(i)  );
         end loop;         
      ELSE 

  -- No more rows - exit
        EXIT; 
      END IF; 
    END LOOP; 

     DBMS_SQL.CLOSE_CURSOR(source_cursor); 
   EXCEPTION 
     WHEN OTHERS THEN 
       IF DBMS_SQL.IS_OPEN(source_cursor) THEN 
         DBMS_SQL.CLOSE_CURSOR(source_cursor); 
       END IF; 
       RAISE; 
  END; 
/
范例

exec ftch('select id, col1, col2 from tab',2);
输出

id= 1
        i=1 col = xx1
        i=2 col = xx2
id= 2
        i=1 col = yy1
        i=2 col = yy2
id= 3
        i=1 col = zz1
        i=2 col = zz2

请看一看oracle动态sql包。对于年轻程序员@OldProgrammer来说,这是一个很好的学习任务,感谢您的启发;)