Can some one give me a small explanation about how and when should someone use sys_refcursor ?

up vote 10 down vote accepted

A cursor is a pointer to a result set for a query. By returning a sys_refcursor you allow the client to fetch as many or few of the rows from the query as it requires. In stateful applications this could be used to page through results.

A cursor can allow more flexibility than writing a PL/SQL function that returns an array as it's completely up to the client how many rows to fetch and when to stop. That said, I've not found many cases where this additional flexibility is useful.

It's worth noting that the sys_refcursor is weakly typed, so you can return pointers to queries which not only have different from or where clauses, but different numbers and types of columns as well. Alternatively you can use strongly typed cursor where the columns in the result set are fixed.

This enables you to write functions which return different queries, like so:

create function get_data ( type varchar2 ) return sys_refcursor as
  ret_cur sys_refcursor;
begin

  if type = 'EMP' then
    open ret_cur for select * from emp;
  elsif type = 'DEPT' then
    open ret_cur for select * from dept;
  end if;

  return ret_cur;
end;

However, if you're using sys_refcursor to create a generic "open a query" function like the above you're probably doing something wrong!

  • @Chris...why is your example function is "wrong?" – Johnny Wu Apr 14 at 15:40
  • @JohnnyWu a "get me anything" function will be harder to manage. How do you test to ensure you've got the right results in all cases? What about security? This may be necessary if you're building a framework. But for general business logic, it's better to have separate get_emps and get_depts functions – Chris Saxon Apr 16 at 14:27

As an example of the possibilities: because it's pl/sql in back, one can define an object to represent a row, define a pl/sql table of those objects,

create type T_MY_TABLE as table of t_my_object;

and end with

OPEN p_recordset FOR select * from table( v_my_table );

So rather than constructing mongo, often dense and/or cryptic direct queries on a database table, one can create an internal table and have the whole power of pl/sql to populate it. And the client collecting the result-set is none the wiser. And changing the definition of the internal table is easier from a management pov than changing a database table.

Also when using report-generators like Jasper, you can push the SQL out of the report and into the database, and just call the procedure to get the recordset, leaving the report-side to focus on the formatting.

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.