Oracle 如何访问结构并获取refcursor的列列表、数据类型?

Oracle 如何访问结构并获取refcursor的列列表、数据类型?,oracle,oracle11g,cursor,sys-refcursor,ref-cursor,Oracle,Oracle11g,Cursor,Sys Refcursor,Ref Cursor,我有一个过程,该过程使用refcursor获得输出,cursor中的数据/结构将是dynami。每次根据输入,游标中的数据类型和列数都会有所不同。那么我如何访问这个结构并获取数据类型呢 PROCEDURE PROC_B ( name_ IN VARCHAR2, date_ IN DATE, code_ IN VARCHAR2,

我有一个过程,该过程使用refcursor获得输出,cursor中的数据/结构将是dynami。每次根据输入,游标中的数据类型和列数都会有所不同。那么我如何访问这个结构并获取数据类型呢

PROCEDURE  PROC_B ( name_     IN       VARCHAR2,
                    date_     IN       DATE,
                    code_           IN       VARCHAR2,
                    sp_name_       IN       VARCHAR2,
                    wrapper_         OUT      sys_refcursor,
                    datyapes_     OUT      VARCHAR2,
                     TS2_     OUT      VARCHAR2,
                     header_   OUT      VARCHAR2)
AS
      TS_         DATE;
BEGIN
      PROC_A (name_, date_, code_, sp_name_, wrapper_, TS_, header_);
      TS2_:= TO_CHAR(TS_, 'MM-DD-YYYY.HH24_MI');

      -- Logic should come here for below requirement 
-- Get the datatypes of variables from wrapper_ (ref cursor datatype) and send them back in datyapes_ . 
 -- Eg1 : If ref cursor returns 2 values with dataytpes VARCHAR2 & Num then o/p should be VARCHAR2|NUMBER , 
 --Eg2 : If ref cursor returns 3 values with dataytpes DATE , TIMESTAMP , VARCHAR2 then o/p should be DATE|TS|VARCHAR2

  END;**

因为您使用的是11g,所以可以使用来查询ref游标,然后在列类型上循环。它们被报告为数字,因此您需要将类型数字转换为字符串()

这是一个演示,让您了解:

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;
/
其中获取输出:

datyapes_: NUMBER|CHAR|DATE

PL/SQL procedure successfully completed.

如问题所示,我将您的变量名保留为
datyapes\u
,但您可能真的有
datatypes\u

,您可以使用
DBMS\u SQL.to\u cursor\u NUMBER
函数将ref游标转换为
DBMS\u SQL
游标。然后,有了光标编号,就可以通过
DBMS\u SQL
对其进行检查和操作。这包括能够描述其列,如下例所示:

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