Sei sulla pagina 1di 10

All the examples in this series have been tested only with Oracle 10g (V10.2).

I didn't really test any of the examples in any of the previous versions. If you have any problems during the execution of these examples, please post in the discussion area. Introduction to REF CURSOR A REF CURSOR is basically a data type. A variable created based on such a data type is generally called a cursor variable. A cursor variable can be associated with different queries at run-time. The primary advantage of using cursor variables is their capability to pass result sets between sub programs (like stored procedures, functions, packages etc.). Let us start with a small sub-program as follows: declare type r_cursor is REF CURSOR; c_emp r_cursor; en emp.ename%type; begin open c_emp for select ename from emp; loop fetch c_emp into en; exit when c_emp%notfound; dbms_output.put_line(en); end loop; close c_emp; end; Let me explain step by step. The following is the first statement you need to understand: type r_cursor is REF CURSOR; The above statement simply defines a new data type called "r_cursor," which is of the type REF CURSOR. We declare a cursor variable named "c_emp" based on the type "r_cursor" as follows: c_emp r_cursor;

Every cursor variable must be opened with an associated SELECT statement as follows: open c_emp for select ename from emp; To retrieve each row of information from the cursor, I used a loop together with a FETCH statement as follows: loop fetch c_emp into en; exit when c_emp%notfound; dbms_output.put_line(en); end loop; I finally closed the cursor using the following statement: close c_emp; %ROWTYPE with REF CURSOR In the previous section, I retrieved only one column (ename) of information using REF CURSOR. Now I would like to retrieve more than one column (or entire row) of information using the same. Let us consider the following example: declare type r_cursor is REF CURSOR; c_emp r_cursor; er emp%rowtype; begin open c_emp for select * from emp; loop fetch c_emp into er; exit when c_emp%notfound; dbms_output.put_line(er.ename || ' - ' || er.sal); end loop; close c_emp; end; In the above example, the only crucial declaration is the following: er emp%rowtype;

The above declares a variable named "er," which can hold an entire row from the "emp" table. To retrieve the values (of each column) from that variable, we use the dot notation as follows: dbms_output.put_line(er.ename || ' - ' || er.sal); Let us consider that a table contains forty columns and I would like to retrieve fifteen columns. In such scenarios, it is a bad idea to retrieve all forty columns of information. At the same time, declaring and working with fifteen variables would be bit clumsy. The next section will explain how to solve such issues. Next: Working with REC

TOOLS YOU CAN USE

advertisement

See Also:
1. 2. 3. Oracle Stored Procedures Extending PL/SQL with Java Libraries, concluded Oracle PL/SQL Subprograms

Until now, we have been working either with %TYPE or %ROWTYPE. This means we are working with either one value or one complete record. How do we create our own data type, with our own specified number of values to hold? This is where TYPE and RECORD come in. Let us consider the following example: declare type r_cursor is REF CURSOR; c_emp r_cursor; type rec_emp is record ( name varchar2(20), sal number(6) ); er rec_emp;

begin open c_emp for select ename,sal from emp; loop fetch c_emp into er; exit when c_emp%notfound; dbms_output.put_line(er.name || ' - ' || er.sal); end loop; close c_emp; end; The most confusing aspect from the above program is the following: type rec_emp is record ( name varchar2(20), sal number(6) ); The above defines a new data type named "rec_emp" (just like %ROWTYPE with limited specified fields) which can hold two fields, namely "name" and "sal." er rec_emp; The above statement declares a variable "er" based on the datatype "rec_emp." This means that "er" internally contains the fields "name" and "job." fetch c_emp into er; The above statement pulls out a row of information (in this case "ename" and "sal") and places the same into the fields "name" and "sal" of the variable "er." Finally, I display both of those values using the following statement: dbms_output.put_line(er.name || ' - ' || er.sal); Next: Working with more than one query wit

Sub-programs can also be called sub-routines. These are nothing but the divisions of the main program. These divisions are named and are executed when they are called by name from the main program. They will not get executed unless they are called. The following is an example: declare type r_cursor is REF CURSOR; c_emp r_cursor; type rec_emp is record ( name varchar2(20), sal number(6) ); er rec_emp; procedure PrintEmployeeDetails is begin loop fetch c_emp into er; exit when c_emp%notfound; dbms_output.put_line(er.name || ' - ' || er.sal); end loop; end; begin for i in (select deptno,dname from dept) loop open c_emp for select ename,sal from emp where deptno = i.deptno; dbms_output.put_line(i.dname); dbms_output.put_line('--------------'); PrintEmployeeDetails; close c_emp; end loop; end; In the above program, the sub-routine is named "PrintEmployeeDetails." You can observe that I am executing (or calling) the sub-routine from within the loop as follows:

for i in (select deptno,dname from dept) loop . . PrintEmployeeDetails; . . end loop; According to the above loop, the sub-routine gets executed for every iteration, which displays the employee information for the respective department. Passing REF CURSOR as parameters to sub-programs In the previous section, we already started working with subprograms (or sub-routines). In this section, I shall extend the same with the concept of "parameters" (or arguments). Every subprogram (or sub-routine) can accept values passed to it in the form of "parameters" (or arguments). Every parameter is very similar to a variable, but gets declared as part of a sub-program. Let us consider the following program: declare type r_cursor is REF CURSOR; c_emp r_cursor; type rec_emp is record ( name varchar2(20), sal number(6) ); procedure PrintEmployeeDetails(p_emp r_cursor) is er rec_emp; begin loop fetch p_emp into er; exit when p_emp%notfound; dbms_output.put_line(er.name || ' - ' || er.sal); end loop; end;

begin for i in (select deptno,dname from dept) loop open c_emp for select ename,sal from emp where deptno = i.deptno; dbms_output.put_line(i.dname); dbms_output.put_line('--------------'); PrintEmployeeDetails(c_emp); close c_emp; end loop; end; From the above program, you can observe the following declaration: procedure PrintEmployeeDetails(p_emp r_cursor) is In the above declaration, "PrintEmployeeDetails" is the name of the sub-routine which accepts "p_emp" as a parameter (of type "r_cursor") and we can use that parameter throughout that subroutine. I hope you enjoyed the article and any comments, suggestions, feedback, bugs, errors, enhancements etc. are highly appreciated at http://jagchat.spaces.live.com

>>> More Oracle Articles

>>> More By Jagadish Chatarji

Disqus
Like

Dislike 16 people liked this. Login


Add New Comment

Post as Image

Sort by popular now

Showing 96 comments

Raj Kannan79

I can understand the program. I don't know where to use this refcursor in program
o o o o o Shivakumar241988

Like Reply 4 months ago 3 Likes

Really this was helpfull.


o o o o o Anonymous2404

Like Reply 6 months ago 2 Likes

Really awesome. This article is simple, straight forward which can be understandable by all. Thanks for your article.

o o o o o

Like Reply 8 months ago 2 Likes

Anonymous1134

Not very informative, U r not explaining the power of ref cursor. It's more of an example of Cursor fetch rather than Ref cursor. You should have included examples of Weak and Strong Ref cursors.
o o o o o Anonymous1844

Like Reply 9 months ago 2 Likes

CREATE OR REPLACE PROCEDURE REF_CURSOR(TABLE_NAME IN VARCHAR) IS type t is ref cursor; c t; v_dept dept%rowtype; type r is record(ename emp.ename%type,job emp.job%type,sal emp.sal%type); v_emp r; v_stud student.name%type; BEGIN if table_name = 'DEPT' then open c for select * from dept; elsif table_name = 'EMP' then open c for select ename,job,sal from emp; elsif table_name = 'STUDENT' then

open c for select name from student; end if; loop if table_name = 'DEPT' then fetch c into v_dept; exit when c%notfound; dbms_output.put_line('Deptno = ' || v_dept.deptno || ' Dname = ' || v_dept.dname || ' Loc = ' || v_dept.loc); elsif table_name = 'EMP' then fetch c into v_emp; exit when c%notfound; dbms_output.put_line('Ename = ' || v_emp.ename || ' Job = ' || v_emp.job || ' Sal = ' || v_emp.sal); elsif table_name = 'STUDENT' then fetch c into v_stud; exit when c%notfound; dbms_output.put_line('Name = ' || v_stud); end if; end loop; close c; END;

Potrebbero piacerti anche