Wednesday 3 April 2013

REF Cursor in Oracle


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;


%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;

Ref cursors have the following characteristics:
----------------------------------------------

A ref cursor is not updatable. The result set represented by the ref cursor is read-only.
 You cannot update the database by using a ref cursor.

A ref cursor is a PL/SQL datatype. You create and return a ref cursor inside a PL/SQL code block.



Passing Ref Cursor  as Parameter to Procedure:
====================================

CREATE OR REPLACE PROCEDURE pass_ref_cur(p_cursor SYS_REFCURSOR) IS

TYPE array_t IS TABLE OF VARCHAR2(4000)
INDEX BY BINARY_INTEGER;

rec_array array_t;

BEGIN
  FETCH p_cursor BULK COLLECT INTO rec_array;

  FOR i IN rec_array.FIRST .. rec_array.LAST
  LOOP
    dbms_output.put_line(rec_array(i));
  END LOOP;
END pass_ref_cur;


Execution
-------------

set serveroutput on

DECLARE
 rec_array SYS_REFCURSOR;
BEGIN
  OPEN rec_array FOR
  'SELECT empname FROM employees';

  pass_ref_cur(rec_array);
  CLOSE rec_array;
END;
/

Example:2
========

CREATE OR REPLACE PROCEDURE child (
 p_NumRecs IN PLS_INTEGER,
 p_return_cur OUT SYS_REFCURSOR)
IS

BEGIN
  OPEN p_return_cur FOR
  'SELECT * FROM all_tables WHERE rownum <= ' || p_NumRecs ;
END child;


CREATE OR REPLACE PROCEDURE parent (pNumRecs VARCHAR2) IS
 p_retcur  SYS_REFCURSOR;
 at_rec    all_tables%ROWTYPE;
BEGIN
  child(pNumRecs, p_retcur);

  FOR i IN 1 .. pNumRecs
  LOOP
    FETCH p_retcur
    INTO at_rec;

    dbms_output.put_line(at_rec.table_name ||
    ' - ' || at_rec.tablespace_name ||
    ' - ' || TO_CHAR(at_rec.initial_extent) ||
    ' - ' || TO_CHAR(at_rec.next_extent));
  END LOOP;
END parent;
/

===============================
The main advantage of ref cursor is

1. We can  return result set to a client which we can't do using normal cursors.
2. It can be passed as parameter to sub programs.



Ur's
AmarAlam

0 comments:

Post a Comment