Professional Documents
Culture Documents
REF CURSOR is nothing but a dynamic cursor which points a select statement at run
time. So we can have multiple select statements defined for a particular cursor unlike
static cursors.
STRONG REF CURSORS are those ref cursors that have a return type defined.
The structure of the SELECT statement (the number and datatypes of the columns) must
match or be compatible with the structure specified in the RETURN clause of the cursor
type declaration statement.
DECLARE
TYPE cur_ref is REF CURSOR RETURN employees%rowtype;
c1 cur_ref; --CURSOR VARIABLE
DECLARATION
er employees%rowtype;
BEGIN
Weak ref cursors can be used for any type of select statements unlike strong ref cursors.
This is because we don't have a return type declared for the type statements.
DECLARE
TYPE cur_REF is REF CURSOR ;
c1 cur_ref;
er employees%rowtype;
BEGIN
OPEN c1 FOR SELECT * FROM EMPLOYEES;
LOOP
fetch c1 into er;
dbms_output.put_line(('FOR 1ST CURSOR'||er.last_name);
exit when(c1%NOTFOUND);
END LOOP;
close c1;
OPEN c1 FOR SELECT * FROM EMPLOYEES WHERE EMPLOYEE_ID=101;
LOOP
fetch c1 into er;
dbms_output.put_line(('FOR 2ND CURSOR'||er.last_name);
exit when(c1%NOTFOUND);
END LOOP;
close c1;
OPEN c1 FOR SELECT * FROM DEPARTMENTS;
LOOP
fetch c1 into er;
dbms_output.put_line(('FOR 3RD CURSOR'|er.last_name);
exit when(c1%NOTFOUND);
END LOOP;
close c1;
END;
So just a simple rule for coding with ref cursor is to declare a type ref cursor. Assign it to
a cursor variable.While opening the cursor attach a for select statement with it. Thats it .
And everything else remains same as it is for a code developed using static cursors.
Use strong type ref cursor if you need records to be fetched from a particular type of
table.
Use weak ref cursor if you are going to fetch record from different tables with different
datatypes and columns.
• Concepts
• PL/SQL Records
o Using %ROWTYPE
• PL/SQL Tables
o Creating a PL/SQL table
o Using a PL/SQL table
o PL/SQL Table Methods
Concepts
• Oracle allows you to define several kinds of composite datatypes, also knows as
collections, including RECORD, PL/SQL TABLE, Nested Table, and VARRAY.
• A composite datatype is different from a scalar datatype in that a composite datatype has
an internal structure.
• We will over PL/SQL records and PL/SQL Tables
PL/SQL Records
• A record is a group of related data items stored in fields, each with its own name and
datatype.
• The structure of a record can be declared explicitly, or declared based on a cursor or
database table.
• Creating a user defined record is a two step process, you first declare a record type and
the declare a record based on that type.
DECLARE
--Create a record type. Note similarity to table
creation syntax.
TYPE emp_record_type IS RECORD
empno NUMBER(10),
ename VARCHAR2(10),
job VARCHAR2(9),
sal NUMBER(8,2));
Using %ROWTYPE
DECLARE
dept_record dept%ROWTYPE;
/* The dept record will have the following structure:
* DEPTNO, NUMBER(2)
* DNAME, VARCHAR2(14)
* LOC, VARCHAR2(13)
*/
BEGIN
...
END;
• There is a small overhead (performance penalty) when using the %ROWTYPE attribute
with anonymous PL/SQL blocks.
• The values within a record type can be assigned or referenced like so
record_name.field_name
emp_record.ename:='GATES';
DECLARE
dept_record1 dept%ROWTYPE;
--base this record structure on the first record
structure
dept_record2 dept_record1%ROWTYPE;
CURSOR dept_cursor IS
SELECT *
FROM dept;
BEGIN
OPEN dept_cursor;
FETCH dept_cursor INTO dept_record1;
CLOSE dept_cursor;
dept_record2:=dept_record1; --assign from one record to
the other.
DBMS_OUTPUT.PUT_LINE(dept_record2.dname);
END;
/
• Note that a user defined record and a record anchored to a database table may have a
compatible datatype, if they match in number, name, and datatype of fields. SInce they
have compatible datatypes, the values can be directly assigned from one row to another.
DECLARE
dept_record1 dept%ROWTYPE;
TYPE dept_record_type IS RECORD (
deptno NUMBER(2),
dname VARCHAR2(14),
loc VARCHAR2(13));
dept_record2 dept_record_type;
CURSOR dept_cursor IS
SELECT *
FROM dept;
BEGIN
OPEN dept_cursor;
FETCH dept_cursor INTO dept_record1;
CLOSE dept_cursor;
dept_record2:=dept_record1; --assign from one record to
the other.
DBMS_OUTPUT.PUT_LINE(dept_record2.dname);
END;
/
PL/SQL Tables
Creating a PL/SQL table is a two step process, first you declare the table type, and then declare
an identifier using that type.
DECLARE
TYPE ename_table_type IS
--This defines the datatype and size of the column.
In this case its anchored to ENAME.
TABLE OF emp.ename%TYPE
--Each row in a PL/SQL table is identified by a
BINARY_INTEGER.
INDEX BY BINARY_INTEGER;
--This creates a table named ename_table with the
structure defined above.
ename_table ename_table_type;
BEGIN
...
END;
/
You can assign and reference elements in a PL/SQL table using an integer to identify the specific
row.
ename_table(1):='My name';
DECLARE
TYPE ename_table_type IS TABLE OF emp.ename%TYPE
INDEX BY BINARY_INTEGER;
ename_table ename_table_type;
v_index BINARY_INTEGER:=1;
BEGIN
FOR emp_record IN (SELECT * FROM emp) LOOP
ename_table(v_index):=emp_record.ename;
v_index:=v_index+1;
END LOOP;
v_index:=ename_table.FIRST;
WHILE ename_table.EXISTS(v_index) LOOP
DBMS_OUTPUT.PUT_LINE('ename_table('||v_index||') '||
ename_table(v_index));
v_index:=ename_table.NEXT(v_index);
END LOOP;
END;
/
• You can create a PL/SQL table of records like so:
DECLARE
TYPE ename_table_type IS
TABLE OF emp%ROWTYPE --PL/SQL column is a record
based on the EMP table.
INDEX BY BINARY_INTEGER;
ename_table ename_table_type;
v_index BINARY_INTEGER:=1;
BEGIN
FOR emp_record IN (SELECT * FROM emp) LOOP
ename_table(v_index):=emp_record;
/* Of course, you could also assign values like so:
* ename_table(v_index).ename:=emp_record.ename;
* ename_table(v_index).job:=emp_record.job;
*/
v_index:=v_index+1;
END LOOP;
v_index:=ename_table.FIRST;
WHILE ename_table.EXISTS(v_index) LOOP
DBMS_OUTPUT.PUT_LINE('ename_table('||v_index||') '
||ename_table(v_index).ename||' is a '||
ename_table(v_index).job);
v_index:=ename_table.NEXT(v_index);
END LOOP;
END;
/