从函数返回游标并在变量中使用它

时间:2015-09-14 17:05:40

标签: oracle plsql oracle-sqldeveloper

我在包中声明了2个函数。

在第一个函数中,我返回一个光标。

在第二个函数中,我调用第一个函数并将返回的光标存储在变量中。

当我尝试打开游标循环时,我收到错误。

这是我的包规范:

create or replace PACKAGE CURSOR_EXAMPLE AS 

  FUNCTION get_cursor ( tId IN NUMBER ) RETURN SYS_REFCURSOR;

  FUNCTION use_cursor ( tId IN NUMBER ) RETURN VARCHAR2;

END CURSOR_EXAMPLE;

这是我的包裹体:

CREATE OR REPLACE 
PACKAGE BODY CURSOR_EXAMPLE AS

  FUNCTION get_cursor ( tId IN NUMBER ) RETURN SYS_REFCURSOR AS

    my_cursor SYS_REFCURSOR;

  BEGIN

    OPEN my_cursor FOR 

       SELECT * 
       FROM example_table eT 
       WHERE eT.PARENT_ID = tId;

      --CLOSE my_cursor;
      RETURN my_cursor;

  END get_cursor;

  FUNCTION use_cursor ( tId IN NUMBER ) RETURN VARCHAR2 AS

    my_cursor SYS_REFCURSOR;

  BEGIN

    my_cursor := get_cursor(tId);

    OPEN my_cursor;

        FOR my_rec in my_cursor

        LOOP

          DBMS_OUTPUT.PUT_LINE('ID: ' || my_rec.table_id );   
          -- find_leaf_node(llf_rec.llf_id)

        END LOOP;

      CLOSE my_cursor;

      RETURN NULL;

  END use_cursor;

END CURSOR_EXAMPLE;

以下是他们访问的表格:

    table_id    parent_id
1   1           (null)  
2   2           1
3   3           2
4   4           3
5   5           4
6   6           1
7   7           6
8   8           1
9   9           8
10  10          1
11  11          10

当我从use_cursor中删除错误并运行get-cursor

select CURSOR_EXAMPLE.get_cursor(3) from dual; 

给了我

{<TABLE_ID=4,PARENT_ID=3>,}

以下是SQL Developer给我的错误:

OPEN my_cursor; - Error(29,5): PLS-00382: expression is of wrong type

FOR my_rec in my_cursor - Error(31,23): PLS-00221: 'MY_CURSOR' is not a procedure or is undefined

我不熟悉pl / sql,所以我不确定这是一个小的语法问题还是不可能。

欢迎任何指示或帮助。 提前谢谢。

1 个答案:

答案 0 :(得分:4)

您无法使用FOR..IN..LOOPSYS_REFCURSOR获取内容。你需要自己做。希望这会让你开始 - 这是你发布的代码的修改版本。

DECLARE
  -- You need a variable to fetch into
  l_record DBA_OBJECTS%ROWTYPE;
  -- This holds the results of use_cursor() function
  dummy varchar2(1);

  FUNCTION get_cursor (tid IN NUMBER)
    RETURN SYS_REFCURSOR AS
    my_cursor   SYS_REFCURSOR;
  BEGIN
    OPEN my_cursor FOR
      SELECT *
      -- Changed to DBA_OBJECTS since I do not have your table
      FROM   dba_objects et
      WHERE  et.object_id < tid;

    --CLOSE my_cursor;
    RETURN my_cursor;
  END get_cursor;

  FUNCTION use_cursor (tid IN NUMBER)
    RETURN VARCHAR2 AS
    my_cursor   SYS_REFCURSOR;
  BEGIN
    my_cursor   := get_cursor (tid);

    LOOP
      FETCH my_cursor INTO l_record;
      EXIT WHEN my_cursor%NOTFOUND;
      DBMS_OUTPUT.put_line ('ID: ' || l_record.object_id);
    END LOOP;

    CLOSE my_cursor;

    RETURN NULL;
  END use_cursor;

BEGIN
  dummy := use_cursor (50);
END;