Home > Software design >  Is there a way to close the cursor after reading it?
Is there a way to close the cursor after reading it?

Time:09-30

working with oracle sql and oracle service bus. I have a problem with closing the connection. An example of a simple procedure I use is the following :

create or replace procedure getempdata(
  v_id in number,
  q out sys_refcursor
)
as
begin
  open q for select * from employees where id = v_id;
end;

I need a way to close the cursor after getting the data from it. but if I use close Q; , I can't read the data returned in service bus adapter . The question is : Is there a way to close the cursor (for memory management) from service bus after reading it? And if there is not, Is there a way to do so from the procedure with returning the data as output?

Note: I don't call the procedure from sql code, so I can close it. I call it as a webservice using service bus webservice that calls the procedure by a database adapter; so I need the data returned in service bus

CodePudding user response:

You'd close it from the caller.

Your procedure (adjusted to Scott's sample schema):

SQL> create or replace procedure getempdata(
  2    v_id in number,
  3    q out sys_refcursor
  4  )
  5  as
  6  begin
  7    open q for select ename from emp where deptno = v_id;
  8  end;
  9  /

Procedure created.

Let's call it:

SQL> set serveroutput on
SQL> declare
  2    l_rc sys_refcursor;
  3    l_ename emp.ename%type;
  4  begin
  5    getempdata(10, l_rc);             --> procedure is called here
  6    loop
  7      fetch l_rc into l_ename;
  8      exit when l_rc%notfound;
  9      dbms_output.put_line(l_ename);
 10    end loop;
 11    close l_rc;                       --> cursor is closed here
 12  end;
 13  /
CLARK
KING
MILLER

PL/SQL procedure successfully completed.

SQL>

CodePudding user response:

Yes, close it once you have read from it (or if an exception occurs that prevents reading from it) using the CLOSE statement.

DECLARE
  v_cur SYS_REFCURSOR;
  v_row EMPLOYEES%ROWTYPE;
BEGIN
  -- call the procedure
  getempdata(1, v_cur);

  -- read the rows
  LOOP
    FETCH v_cur INTO v_row;
    EXIT WHEN v_cur%NOTFOUND;
    DBMS_OUTPUT.PUT_LINE(v_row.id);
  END LOOP;
  
  -- close the cursor
  CLOSE v_cur;
EXCEPTION
  WHEN OTHERS THEN -- Handling OTHERS is bad practice, normally you should be more specific
    IF v_cur%ISOPEN THEN
      CLOSE v_cur;
    END IF;
END;
/

fiddle

  • Related