oracle动态游标问题: 游标查询的内容是 动态生成的,然后里面具体有多少个字段没办法事先知道,而动态游标赋值一定要用fetch到一个变量,有没办法把动态游标内容赋值到一个记录集或者表中,而这个表的字段和记录集字段是没办法预先定义好的,而是通过系统动态生成的!
具体例子如下:
declare 
  -- Local variables here
  v_sql VARCHAR2(1024);
  cur SYS_REFCURSOR;
  v_column VARCHAR2(1024);
  v_exe VARCHAR2(1024);
begin
  ---v_sql 是通过一连串的复杂逻辑程序生成的动态内容的 在这里就简单写了
  v_sql:='select C_001,b_002,d_003 ..../*具体有多少个字段没办法事先知道*/from table1,table2 .../*具体有多少个字段没办法事先知道*/tablen where 1=1 and /*复杂条件*/';
   v_column:= 'C_001+b_002/d_003';--这个变量也是通过复杂的逻辑生成的 没办法事先知道的 但是这里的字段都在 v_sql 中有 
   --在这里 在 字段前面加上表模式 (用正则表达式怎么写 regexp_replace) 
   --v_column := replace(replace(REPLACE(v_column,'b_','c.b_'),'c_','c.c_'),,'c_','c.d_');
   v_column := regexp_replace(v_column,'(c_|d_|b_)','c.\1');
V_CASE_WHEN:=regexp_replace(upper(V_CASE_WHEN),'(MT_|T_|M_|B_|R_)', 'CUR_LOOP.\1');
  OPEN cur FOR v_sql;
   LOOP
   FETCH cur   BULK COLLECT INTO  e_table ;--但是这边表/记录集 里面的字段没办法定义 因为没办法事先知道表的结构 有没 什么办法(定义 e_talbe )
   FOR i  IN 1..e_table(i);
   v_exe:='INSERT INTO table_a SELECT'|| v_column||' FROM dual' ;  /*这里的动态生成的*/
   EXECUTE IMMEDIATE v_exe;
   COMMIT;
  END LOOP;
end;

解决方案 »

  1.   

    刚找了下ORACLE官方文档,有这种例子的:
    11R2PLSQL Packages and Types Reference_e10577.pdf (DBMS_SQL 133-87)
    TO_CURSOR_NUMBER Function
    CREATE OR REPLACE PROCEDURE DO_QUERY(sql_stmt VARCHAR2) IS
      TYPE CurType IS REF CURSOR;
      src_cur         CurType;
      curid           NUMBER;
      desctab         DBMS_SQL.DESC_TAB;
      colcnt          NUMBER;
      namevar         VARCHAR2(50);
      numvar          NUMBER;
      datevar         DATE;
      empno           NUMBER := 100;
    BEGIN
        -- sql_stmt := 'select ...... from employees where employee_id = :b1';
        OPEN src_cur FOR sql_stmt USING empno;
     
        -- Switch from native dynamic SQL to DBMS_SQL
        curid := DBMS_SQL.TO_CURSORID(src_cur);
     
        DBMS_SQL.DESCRIBE_COLUMNS(curid, colcnt, desctab);
     
        -- Define columns
        FOR i IN 1 .. colcnt LOOP
            IF desctab(i).col_type = 2 THEN
               DBMS_SQL.DEFINE_COLUMN(curid, i, numvar);
            ELSIF desctab(i).col_type = 12 THEN
                DBMS_SQL.DEFINE_COLUMN(curid, i, datevar);
    .......
             ELSE
                DBMS_SQL.DEFINE_COLUMN(curid, i, namevar);
             END IF;
        END LOOP;
     
      -- Fetch Rows
        WHILE DBMS_SQL.FETCH_ROWS(curid) > 0 LOOP
            FOR i IN 1 .. colcnt LOOP
              IF (desctab(i).col_type = 1) THEN
                DBMS_SQL.COLUMN_VALUE(curid, i, namevar);
             ELSIF (desctab(i).col_type = 2) THEN
                DBMS_SQL.COLUMN_VALUE(curid, i, numvar);
              ELSIF (desctab(i).col_type = 12) THEN
                DBMS_SQL.COLUMN_VALUE(curid, i, datevar);
    ....
              END IF;
            END LOOP;
        END LOOP;
     
        DBMS_SQL.CLOSE_CURSOR(curid);
    END;