Skip to Main Content
  • Questions
  • How to test a function returning a ref cursor from sqlplus

Breadcrumb

Question and Answer

Connor McDonald

Thanks for the question, oracle.

Asked: September 14, 2001 - 6:19 pm UTC

Last updated: August 12, 2019 - 3:45 am UTC

Version: 8.1.7

Viewed 50K+ times! This question is

You Asked

My function returns ref cursor. At the sqlplus prompt how should I test my functions , and see the rows in the ref cursor.

the same from within a procedure how should I do it.



For the function I tried to do the following:

sqlplus>variable x refcursor

begin

open c for 'select f_function(USA,SYSDATE,SYSDATE,0) into :x from dual'

end;

print :x

I want to see the rows returned by my function f_function , how should I do it.


When Iam trying to do

sqlplus>select f_function(USA,SYSDATE,SYSDATE,0) from dual;
it is not working Iam getting a wrong datatype error.


Please guide.

Junior

and Tom said...

Ok, here is an example of a procedure, function and anonymous block that return ref cursors in sqlplus:

ops$tkyte@ORA817DEV.US.ORACLE.COM> create or replace package types
2 as
3 type rc is ref cursor;
4 end;
5 /

Package created.

ops$tkyte@ORA817DEV.US.ORACLE.COM>
ops$tkyte@ORA817DEV.US.ORACLE.COM>
ops$tkyte@ORA817DEV.US.ORACLE.COM> create or replace procedure get_cursor_proc( p_cursor in out types.rc )
2 is
3 begin
4 open p_cursor for select * from dual;
5 end;
6 /

Procedure created.

ops$tkyte@ORA817DEV.US.ORACLE.COM>
ops$tkyte@ORA817DEV.US.ORACLE.COM> create or replace function get_cursor_func return types.rc
2 as
3 l_cursor types.rc;
4 begin
5 open l_cursor for select * from dual;
6 return l_cursor;
7 end;
8 /

Function created.

ops$tkyte@ORA817DEV.US.ORACLE.COM>
ops$tkyte@ORA817DEV.US.ORACLE.COM>
ops$tkyte@ORA817DEV.US.ORACLE.COM> variable x refcursor
ops$tkyte@ORA817DEV.US.ORACLE.COM> set autoprint on
ops$tkyte@ORA817DEV.US.ORACLE.COM>
ops$tkyte@ORA817DEV.US.ORACLE.COM> REM procedure
ops$tkyte@ORA817DEV.US.ORACLE.COM> exec get_cursor_proc(:x)

PL/SQL procedure successfully completed.


D
-
X

ops$tkyte@ORA817DEV.US.ORACLE.COM>
ops$tkyte@ORA817DEV.US.ORACLE.COM> REM function
ops$tkyte@ORA817DEV.US.ORACLE.COM> exec :x := get_cursor_func

PL/SQL procedure successfully completed.


D
-
X

ops$tkyte@ORA817DEV.US.ORACLE.COM>
ops$tkyte@ORA817DEV.US.ORACLE.COM> REM anonymous block
ops$tkyte@ORA817DEV.US.ORACLE.COM> begin
2 open :x for select * from dual;
3 end;
4 /

PL/SQL procedure successfully completed.


D
-
X




Rating

  (10 ratings)

Is this answer out of date? If it is, please let us know via a Comment

Comments

cool, a day to day solution , and one more thing==

A reader, September 15, 2001 - 8:27 pm UTC

why doesnt select get_cursor_func from dual, work when it is returning a ref cursor

Tom Kyte
September 16, 2001 - 3:20 pm UTC

because a ref cursor is not a sqltype. Only SQL types can be selected from a user defined function (eg: select function_returning_boolean from dual won't work either)

what is the difference

A reader, September 15, 2001 - 10:52 pm UTC

Tom

What is a ref cursor.

What is the difference betweeen a regular cursor and a refcursor.

and

This is a often asked question in interviews.



Tom Kyte
September 16, 2001 - 3:22 pm UTC

I ref cursor is a variable that holds a cursor. Underneath, it is a "regular" cursor. It is a pointer to a cursor.

Normally a cursor is a static thing, it points to A query:


declare
c1 cursor for select * from emp;
....


It is clear that C1 will run that query and none other. A ref cursor can have an arbitrary query associated with it:

declare
type rc is ref cursor;
c1 rc;
begin
if ( a = b ) then
open c1 for select * from emp;
else
open c1 for select * from dept;
end if;
.....

Thank you , finally the concept is clear to me

Chen, September 16, 2001 - 7:37 pm UTC

Tom, Does oracle has any document which define all the terms like refcursor, vaarray, nested table etc etc etc.

What I mean is a document which is like a dictionary of the above terms and more.

Tom Kyte
September 16, 2001 - 9:22 pm UTC

These constructs are documented as they are encounted. All of the above are in the plsql programmers guide (amongst others).

dbms_output.put_line and print

Thanks, September 16, 2001 - 11:04 pm UTC

Internally are dbms_output.put_line and print same. Do they work the same way.

In the refcursor function example you have given, if I have a dbms_output call, will it be displayed when I give the print :x command.



Tom Kyte
September 17, 2001 - 7:40 am UTC

dbms_output and print are very very very different.

dbms_output.put_line just adds data to a big array. After your call completes, sqlplus reads this buffered data via dbms_output.get_lines and prints it.

PRINT prints the contents of a bind variable.

Closing A Ref Cursor

Anup Singh, September 17, 2001 - 6:54 am UTC

Hi Tom,

Is It Not Required To Explicit Close A Cursor Opened By Ref Cursor ? Why ?

Thanks And Regards


Tom Kyte
September 17, 2001 - 7:38 am UTC

The client is responsible for closing the cursor. In this case, the client is ALWAYS sqlplus and sqlplus issues the close for us. If the recipient of the ref cursor was another PLSQL routine, it would be upto that plsql routine to close it (if your java/jdbc client gets it - they close it and so on)

According to the def given in the sqlplus guide , an anonymous block

Kulguru, December 26, 2001 - 7:44 pm UTC

... need not have begin and end statements

"A PL/SQL program unit that has no name and does not require the explicit presence of the BEGIN and END keywords to enclose the executable statements. "

But in your example for anonymous block , you have given the begin and end statements.

Can you clear this confusion.



Tom Kyte
December 26, 2001 - 8:58 pm UTC

ops$tkyte@ORA817DEV.US.ORACLE.COM> REM procedure
ops$tkyte@ORA817DEV.US.ORACLE.COM> exec get_cursor_proc(:x)

PL/SQL procedure successfully completed.


D
-
X



that is an anonymous block as well.  It needs not have a begin/end in sqlplus (only in sqlplus)


I was showing how to open a ref cursor using a PROCEDURE call and in just an anonymous block -- which could have been coded as:


SQL> exec open :x for select * from dual;

just as easily, instead of:

ops$tkyte@ORA817DEV.US.ORACLE.COM> begin
  2          open :x for select * from dual;
  3  end;
  4  /


 

SWEET

A reader, July 31, 2006 - 11:30 pm UTC


Sys_RefCursor variable

regi, August 10, 2019 - 10:47 pm UTC

var1 Sys_RefCursor variable;

open var1 for select .....(complex query) ....

Actual execution of the complex query take place during the above open ?
Connor McDonald
August 12, 2019 - 3:45 am UTC

The word I often use with Oracle is "lazy". Not in a bad way, but for example, if I had psuedo-code like:

open cursor;
if today is tuesday then
  fetch from cursor;
end if;


then if I was the database, I would not perform the open command until I actually had to do the first fetch, because it is a waste of time.

But if the code was ever so slightly different, eg

open cursor which has a select-for-update
if today is tuesday then
  fetch from cursor;
end if;


then it doesn't matter if it is tuesday or any other day, I would *have* to open that cursor immediately because it has an impact on other sessions (ie, it locks some rows).

So typically you'll often see that the database (in many many areas) will avoid doing work unless it absolutely has to. For cursors, in most cases, we will not actually process the "open" command until we hit the first fetch call.

sys_refcursor

Regi, August 10, 2019 - 11:21 pm UTC

Tom - when does the actual complex query get executed in above case ?

sys_refcursor

Regi, August 11, 2019 - 9:31 am UTC

cont...above

the only statement after opening the ref cursor above is

xmltype.createxml which uses the sys_refcursor variable as input

is the complex query executed while opening the ref cursor or while doing the xml conversion above ?


More to Explore

PL/SQL demos

Check out more PL/SQL tutorials on our LiveSQL tool.

PL/SQL docs

PL/SQL reference manual from the Oracle documentation library