I have a procedure which gets me the output with refcursor and data/structure in cursor will be dynami. Each time depending on inputs datatypes and no of columns in cursor w
Since you're on 11g, you can use the dbms_sql package to interrogate your ref cursor, and then loop over the column types. They are reported as numbers so you'll need to translate the type numbers to strings (listed here).
This is a demo to give you the idea:
set serveroutput on
DECLARE
-- mimicking your procedure arguments
wrapper_ SYS_REFCURSOR;
datyapes_ VARCHAR(100);
L_COLS NUMBER;
L_DESC DBMS_SQL.DESC_TAB;
L_CURS INTEGER;
L_VARCHAR VARCHAR2(4000);
BEGIN
-- fake cursor, instead of procedure call
open wrapper_ for q'[select 42, 'Test', date '2017-03-02' from dual]';
L_CURS := DBMS_SQL.TO_CURSOR_NUMBER(wrapper_);
DBMS_SQL.DESCRIBE_COLUMNS(C => L_CURS, COL_CNT => L_COLS,
DESC_T => L_DESC);
FOR i IN 1..L_COLS LOOP
datyapes_ := datyapes_ || CASE WHEN i > 1 THEN '|' END
|| CASE L_DESC(i).col_type
WHEN 1 THEN 'VARCHAR2'
WHEN 2 THEN 'NUMBER'
WHEN 12 THEN 'DATE'
WHEN 96 THEN 'CHAR'
WHEN 180 THEN 'TS'
-- more types as needed
ELSE 'unknown'
END;
END LOOP;
DBMS_SQL.CLOSE_CURSOR(L_CURS);
-- just for debug
dbms_output.put_line('datyapes_: ' || datyapes_);
END;
/
which gets output:
datyapes_: NUMBER|CHAR|DATE
PL/SQL procedure successfully completed.
I've kept your variable name as datyapes_
as shown in the question, but perhaps you really have datatypes_
.
You can convert the ref cursor to a DBMS_SQL
cursor using the DBMS_SQL.TO_CURSOR_NUMBER
function. Then, having the cursor number, you can inspect manipulate it via DBMS_SQL
. This includes being able to describe it's columns, as shown in the example below:
DECLARE
l_rc SYS_REFCURSOR;
l_cursor_number INTEGER;
l_col_cnt INTEGER;
l_desc_tab DBMS_SQL.desc_tab;
l_col_num INTEGER;
BEGIN
OPEN l_rc FOR 'SELECT object_name, object_type, last_ddl_time FROM dba_objects where rownum <= 10';
l_cursor_number := DBMS_SQL.to_cursor_number (l_rc);
DBMS_SQL.describe_columns (l_cursor_number, l_col_cnt, l_desc_tab);
l_col_num := l_desc_tab.FIRST;
IF (l_col_num IS NOT NULL) THEN
LOOP
DBMS_OUTPUT.put_line ('Column #' || l_col_num);
DBMS_OUTPUT.put_line ('...name: ' || l_desc_tab (l_col_num).col_name);
DBMS_OUTPUT.put_line ('...type: ' || l_desc_tab (l_col_num).col_type);
DBMS_OUTPUT.put_line ('...maxlen: ' || l_desc_tab (l_col_num).col_max_len);
-- ... other fields available in l_desc_tab(l_col_num) too.
l_col_num := l_desc_tab.NEXT (l_col_num);
EXIT WHEN (l_col_num IS NULL);
END LOOP;
END IF;
DBMS_SQL.close_cursor (l_cursor_number);
END;
Column #1
...name: OBJECT_NAME
...type: 1
...maxlen: 128
Column #2
...name: OBJECT_TYPE
...type: 1
...maxlen: 23
Column #3
...name: LAST_DDL_TIME
...type: 12
...maxlen: 7