A resposta curta é, você não pode. Você precisaria definir uma variável para cada coluna que será retornada.
DECLARE
P_RS SYS_REFCURSOR;
L_T_COL1 T.COL1%TYPE;
L_T_COL1 T.COL2%TYPE;
...
E, em seguida, busque na lista de colunas:
FETCH P_RS INTO L_T_COL1, L_T_COL2, ... ;
Isso é doloroso, mas gerenciável, desde que você saiba o que está esperando no cursor de referência. Usando
T.*
no seu procedimento torna isso frágil, pois adicionar uma coluna à tabela quebraria o código que pensa que sabe quais colunas existem e em que ordem elas estão. consistentemente - já vi lugares onde a ordenação das colunas é diferente em diferentes ambientes). Você provavelmente vai querer ter certeza de que está selecionando apenas as colunas com as quais realmente se importa, para evitar ter que definir variáveis para coisas que você nunca lerá. A partir do 11g você pode usar o
DBMS_SQL
pacote para converter seu sys_refcursor
em um DBMS_SQL
cursor, e você pode interrogá-lo para determinar as colunas. Apenas como exemplo do que você pode fazer, isso imprimirá o valor de cada coluna em cada linha, com o nome da coluna:DECLARE
P_RS SYS_REFCURSOR;
L_COLS NUMBER;
L_DESC DBMS_SQL.DESC_TAB;
L_CURS INTEGER;
L_VARCHAR VARCHAR2(4000);
BEGIN
CAPITALEXTRACT(P_RS => P_RS);
L_CURS := DBMS_SQL.TO_CURSOR_NUMBER(P_RS);
DBMS_SQL.DESCRIBE_COLUMNS(C => L_CURS, COL_CNT => L_COLS,
DESC_T => L_DESC);
FOR i IN 1..L_COLS LOOP
DBMS_SQL.DEFINE_COLUMN(L_CURS, i, L_VARCHAR, 4000);
END LOOP;
WHILE DBMS_SQL.FETCH_ROWS(L_CURS) > 0 LOOP
FOR i IN 1..L_COLS LOOP
DBMS_SQL.COLUMN_VALUE(L_CURS, i, L_VARCHAR);
DBMS_OUTPUT.PUT_LINE('Row ' || DBMS_SQL.LAST_ROW_COUNT
|| ': ' || l_desc(i).col_name
|| ' = ' || L_VARCHAR);
END LOOP;
END LOOP;
DBMS_SQL.CLOSE_CURSOR(L_CURS);
END;
/
Isso não é muito prático e, para resumir, estou tratando todos os valores como uma string, pois quero apenas imprimi-los de qualquer maneira. Veja os documentos e procure exemplos para aplicações mais práticas.
Se você quiser apenas algumas colunas do seu cursor ref, suponho que você possa fazer um loop em
l_desc
e registre a posição em que column_name
é o que você estiver interessado, como uma variável numérica; você poderia então se referir à coluna por essa variável mais tarde, onde normalmente usaria o nome em um loop de cursor. Depende do que você está fazendo com os dados. Mas a menos que você esteja esperando não saber a ordem das colunas que você está recebendo, o que é improvável, pois você parece controlar o procedimento - e supondo que você se livre do
.*
s - provavelmente é muito melhor reduzir as colunas retornadas ao mínimo necessário e apenas declará-las individualmente.