【问题标题】:How to access the structure and get the column list ,datatypes of refcursor?如何访问结构并获取列列表,refcursor的数据类型?
【发布时间】:2017-07-22 15:10:18
【问题描述】:

我有一个程序可以让我得到带有 refcursor 的输出,并且光标中的数据/结构将是动态的。每次取决于输入数据类型,游标中的列数会有所不同。那么如何访问这个结构并获取数据类型呢?

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;**

【问题讨论】:

    标签: oracle oracle11g cursor sys-refcursor ref-cursor


    【解决方案1】:

    您可以使用DBMS_SQL.TO_CURSOR_NUMBER 函数将引用光标转换为DBMS_SQL 光标。然后,有了光标编号,您可以通过DBMS_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
    

    【讨论】:

      【解决方案2】:

      由于您使用的是 11g,因此您可以使用 the dbms_sql package 来询问您的引用光标,然后遍历列类型。它们以数字形式报告,因此您需要将类型数字转换为字符串 (listed here)。

      这是一个演示给你的想法:

      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_,但也许您确实有datatypes_

      【讨论】:

        猜你喜欢
        • 2021-12-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-09-14
        • 2017-02-19
        相关资源
        最近更新 更多