Domanda

I am having trouble fetching from an open ref_cursor in PL/SQL when it is returned from a function. When I put the exact same fetch statement in the body of the function in place of the return statement then it works fine.

function GetBound(p_lat in number, p_long in number) return ref_cursor
IS
v_rc_ref_cursor sys_refcursor;
BEGIN

open v_rc_ref_cursor for select * from state_bound;
return v_rc_ref_cursor;

END;

Now if I call it from an anonymous plsql block I get the error "ORA-01001: invalid cursor"

    DECLARE

    v_rc_ref_cursor sys_refcursor;
    v1 number(38);
    v2 varchar2(50);
    v3 number(38);
    v4 varchar2(50);
    BEGIN

    v_rc_ref_cursor := GetBound(122.0928,-18.6974);

    fetch v_rc_ref_cursor into v1, v2, v3, v4;
    close v_rc_ref_cursor;
    DBMS_OUTPUT.PUT_LINE(v1 || v2 || v3 || v4);

    END;

However if I put the anonymous block into the actual function it all works. See below:

function GetBound(p_lat in number, p_long in number) return ref_cursor
IS

v_rc_ref_cursor sys_refcursor;
v1 number(38);
v2 varchar2(50);
v3 number(38);
v4 varchar2(50);

BEGIN

open v_rc_ref_cursor for select * from state_bound;
-- return v_rc_ref_cursor;

fetch v_rc_ref_cursor into v1, v2, v3, v4;
close v_rc_ref_cursor;
DBMS_OUTPUT.PUT_LINE(v1 || v2 || v3 || v4);

END;

I have read around and found some examples of people doing what I'm doing here so to my knowledge this should work. eg. https://community.oracle.com/thread/888365

Could someone help me figure out what I'm doing wrong here?

È stato utile?

Soluzione 2

The way I ended up solving this problem was changing the return type from ref_cursor to sys_refcursor. It seems like a silly way to fix it but it worked with that change. code:

function GetBound(p_lat in number, p_long in number) return sys_refcursor
IS
v_rc_ref_cursor sys_refcursor;
BEGIN

open v_rc_ref_cursor for select * from state_bound;
return v_rc_ref_cursor;

END;

Altri suggerimenti

I don't think that you have provided the exact content of your session here, otherwise you wouldn't have managed to create the second version of your function without compilation error as there is no return statement.

So long as ref_cursor has been declared by a TYPE statement inside your PL/SQL, I don't see any problem in using it as the returned type of your function. Here is a similar example by using the hr.employees sample table:

--
set serveroutput on
--
<<bk1>>
declare
    type ref_cursor is ref cursor;
-- 
    fname   hr.employees.first_name%type;
    empCur  sys_refcursor;
-- 
    function testFun
    (
        p_depid in hr.employees.department_id%type
    )
    return ref_cursor
    is
    begin
        <<bk2>>
        declare
            empCur sys_refcursor;
        begin
            open
                bk2.empCur
            for
                select
                    t1.first_name
                from
                    hr.employees t1
                where
                    t1.department_id = p_depid;
    --         
    -- 
            return bk2.empCur;
        end;
    end testFun;
begin
    bk1.empCur := bk1.testFun(p_depid => 100);
--     
    loop
        fetch
            bk1.empCur
        into
            bk1.fname;
--             
        exit when bk1.empCur%notfound;
--         
        sys.dbms_output.put_line('fname = ' || bk1.fname);
    end loop;
--     
    close bk1.empCur;
end;
/
--
show errors;
--     
set serveroutput off

And the output

No errors.
fname = Nancy
fname = Daniel
fname = John
fname = Ismael
fname = Jose Manuel
fname = Luis

PL/SQL procedure successfully completed.


SQL> 
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top