首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >读取不同游标的Oracle泛型函数

读取不同游标的Oracle泛型函数
EN

Stack Overflow用户
提问于 2021-07-16 08:52:23
回答 1查看 236关注 0票数 0

是否可以将游标数据提取到具有动态游标参数的数组或表中?

示例:我们有3个函数fct1()、fct2()、fct3()。它们都返回具有不同数据的游标(来自不同的表),它们的大小介于20到100之间。我想用一个泛型函数调用这个3函数,填充一个VARCHAR2数组,例如打印这个数组。

我已经了解了如何将游标提取到VARRAY或VARCHAR2中,但是需要指定将哪个游标值添加到数组中。

代码语言:javascript
复制
CREATE OR REPLACE PACKAGE BODY CURSOR_EXAMPLE AS


    FUNCTION fct1 (param01 IN VARCHAR2) RETURN SYS_REFCURSOR AS
    my_cursor SYS_REFCURSOR;
    BEGIN
        OPEN my_cursor FOR 
            SELECT a, b, c FROM table1, table2, table3;
        RETURN my_cursor;
    END fct1;


    FUNCTION fct2 (param01 IN VARCHAR2) RETURN SYS_REFCURSOR AS
        my_cursor SYS_REFCURSOR;
    BEGIN
        OPEN my_cursor FOR 
            SELECT q, w, e, r, t, y FROM table4, table5;
        RETURN my_cursor;
    END fct2;
    
    
    FUNCTION fct3 (param01 IN VARCHAR2, param02 IN VARCHAR2, param03 IN VARCHAR2) RETURN SYS_REFCURSOR AS
        my_cursor SYS_REFCURSOR;
    BEGIN
        OPEN my_cursor FOR 
            SELECT x, y, z FROM table6, table7, table8, table8;
        RETURN my_cursor;
    END fct3;
    
    
    PROCEDURE generic_function (fct IN NUMBER, param01 IN VARCHAR2, param02 IN VARCHAR2, param03 IN VARCHAR2, cursor_out OUT SYS_REFCURSOR)
    AS
    BEGIN
        IF fct = 1
            cursor_out := fct1(param01);
        ELSE IF fct = 2
            cursor_out := fct2(param01);
        ELSE IF
            cursor_out := fct3(param01, param02, param03);
        END IF;
        
        LOOP
            FETCH cursor_out INTO
                -- HERE DEPENDING ON fct1, 2 and 3 add cursor_out variable into a VARRAY (extend it as needed)
                
            
            EXIT WHEN cursor_out%NOTFOUND;
            
        END LOOP;
        
        -- PRINT VARRAY
        
    END generic_function;


END CURSOR_EXAMPLE;
EN

回答 1

Stack Overflow用户

发布于 2021-07-16 18:55:12

似乎您正在尝试设计一种动态方法来发现游标中包含哪些列。

有一种方法,但它涉及使用DBMS_SQL,一旦您将游标转换为DBMS_SQL游标,您就必须在处理记录时始终使用DBMS_SQL

下面是一个测试函数的示例,它可以返回四个不同游标中的一个,而不需要静态定义类型:

代码语言:javascript
复制
CREATE OR REPLACE FUNCTION get_test_cursor (n in number default 1) return SYS_REFCURSOR
IS
  c SYS_REFCURSOR;
BEGIN
   IF n = 1
   THEN
      OPEN c FOR SELECT 'A' f1, 'B' f2 FROM DUAL;
   END IF;

   IF n = 2
   THEN
      OPEN c FOR SELECT cast(1.234 as number(6,2)) n1, cast(12 as number(8)) n2, 'C' f3 FROM DUAL;
   END IF;

   IF n = 3
   THEN
      OPEN c FOR select * from all_objects;
   END IF;
   
   if n = 4
   then
      OPEN c FOR select sysdate as current_dt from dual;
   end if;
   return c;
END;
/

现在,我们可以使用DBMS_SQL包首先使用dbms_sql.to_cursor_number将游标从REF游标转换为游标号。一旦我们这样做了,我们就可以使用DBMS_SQL API的其余部分来检查游标并处理它的数据。

代码语言:javascript
复制
declare
  cur sys_refcursor;
  c number;
  col_cnt     INTEGER;
  rec_tab     DBMS_SQL.DESC_TAB;
  --
  -- This is a crude helper procedure to display one line of "DESCRIBE" output
  --
  PROCEDURE print_rec(rec in DBMS_SQL.DESC_REC) IS
  BEGIN
    DBMS_OUTPUT.PUT_LINE(rpad(rec.col_name, 41) || ' ' ||
    rpad(case when rec.col_null_ok then ' ' else 'NOT NULL' end, 8) || ' ' ||
    case when rec.col_type = DBMS_TYPES.TYPECODE_VARCHAR or rec.col_type = DBMS_TYPES.TYPECODE_VARCHAR2 then
      'VARCHAR2(' || rec.col_max_len || ')'
    when rec.col_type = DBMS_TYPES.TYPECODE_CHAR then
      'CHAR(' || rec.col_max_len || ')'
    when rec.col_type = DBMS_TYPES.TYPECODE_NUMBER then
      case when rec.col_precision = 0 and rec.col_scale = -127 then 'NUMBER'
      when rec.col_scale = 0 then 'NUMBER('||rec.col_precision||')'
      else 'NUMBER(' || rec.col_precision || ', ' || rec.col_scale || ')'
      end
    when rec.col_type = DBMS_TYPES.TYPECODE_DATE then
      'DATE'
    else
      'UNKNOWN'
    end);
  END;
begin
  cur := test_cursor(3);
  --
  -- Convert the REF_CUR to a cursor number
  --
  c := dbms_sql.to_cursor_number(cur);
  --
  -- Use an API call to describe the columns
  --
  DBMS_SQL.DESCRIBE_COLUMNS(c, col_cnt, rec_tab);
  --
  -- Now loop through the columns and show them
  --
  dbms_output.put_line('Name                                      Null?    Type');
  dbms_output.put_line('----------------------------------------- -------- ----------------------------');
  for j in 1..col_cnt loop
    print_rec(rec_tab(j));
  end loop;
  --
  -- We can do other things at this point. 
  -- When done, close the cursor.
  --
  DBMS_SQL.CLOSE_CURSOR(c);
end;
/

下面是传入3的输出,它查询ALL_OBJECTS视图:

代码语言:javascript
复制
Name                                      Null?    Type
----------------------------------------- -------- ----------------------------
OWNER                                     NOT NULL VARCHAR2(128)
OBJECT_NAME                               NOT NULL VARCHAR2(128)
SUBOBJECT_NAME                                     VARCHAR2(128)
OBJECT_ID                                 NOT NULL NUMBER
DATA_OBJECT_ID                                     NUMBER
OBJECT_TYPE                                        VARCHAR2(23)
CREATED                                   NOT NULL DATE
LAST_DDL_TIME                             NOT NULL DATE
TIMESTAMP                                          VARCHAR2(19)
STATUS                                             VARCHAR2(7)
TEMPORARY                                          VARCHAR2(1)
GENERATED                                          VARCHAR2(1)
SECONDARY                                          VARCHAR2(1)
NAMESPACE                                 NOT NULL NUMBER
EDITION_NAME                                       VARCHAR2(128)
SHARING                                            VARCHAR2(13)
EDITIONABLE                                        VARCHAR2(1)
ORACLE_MAINTAINED                                  VARCHAR2(1)

一旦您能够看到游标的列,就可以解决创建一个使用随机游标和填充数组的动态过程的问题。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/68406213

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档