1. Purpose
2. Function that returns an INDEX BY table
3. Function that returns a NESTED table
4. Function that returns a cursor
5. Another function that return a cursor
How, in a client side
application, to use a record set provided by a stored function ?
A record set can be returned
by a function (or by an OUT procedure parameter) in two ways :
Ø A REF CURSOR
Ø A collection
(NESTED or INDEX BY table)
Here is some basic examples of stored functions
that return a record set to a client side application.
q The database
package:
CREATE OR REPLACE PACKAGE PKG_CUR IS -- Collection of EMP raws -- TYPE TYP_REC_EMP IS TABLE OF EMP%ROWTYPE INDEX BY BINARY_INTEGER ; -- Function that returns a collection -- FUNCTION Get_Raws RETURN TYP_REC_EMP ; END PKG_CUR ; / |
CREATE OR REPLACE PACKAGE BODY PKG_CUR IS FUNCTION Get_Raws RETURN TYP_REC_EMP IS tab TYP_REC_EMP ; Begin -- Populate the collection -- Select * BULK COLLECT Into tab From EMP ; -- Return the collection -- RETURN tab ; End ; END PKG_CUR ; / |
q The client side
request:
SQL> set serveroutput on SQL> set pagesize 100 SQL> Declare 2 tab PKG_CUR.TYP_REC_EMP ; 3 Begin 4 5 tab := PKG_CUR.Get_Raws ; 6 7 For i IN tab.first .. tab.Last Loop 8 Dbms_Output.Put_Line( tab(i).ename ) ; 9 End loop ; 10 End ; 11 / SMITH ALLEN WARD JONES MARTIN BLAKE CLARK SCOTT KING TURNER ADAMS JAMES FORD MILLER PL/SQL procedure successfully completed. SQL> |
q
The database types:
drop type
TYP_TAB_REC_EMP / |
q
The function:
CREATE OR REPLACE function ret_cur return
TYP_TAB_REC_EMP Is tab
TYP_TAB_REC_EMP := TYP_TAB_REC_EMP(NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL); Cursor
C_EMP is Select * From EMP ; i
pls_integer := 0 ; Begin For CEMP in
C_EMP Loop tab.extend
; i := i +
1 ; tab(i) :=
TYP_REC_EMP(CEMP.EMPNO,CEMP.ENAME,CEMP.JOB,CEMP.MGR,CEMP.HIREDATE,CEMP.SAL,CEMP.COMM,CEMP.DEPTNO); End loop ; return tab
; End; / |
q
The client side request:
Sql*Plus, Forms
SQL> set linesize 200 SQL> |
// Select the ENAME column
from the EMP table ResultSet rset = stmt.executeQuery
("select * from table(ret_cur) where deptno=10"); // Iterate through the
result and print the employee names while (rset.next ())
System.out.println (rset.getString (2)); |
q The database function:
CREATE OR REPLACE FUNCTION Return_Cursor( PC$Select IN VARCHAR2 ) RETURN SYS_REFCURSOR IS cc SYS_REFCURSOR ; BEGIN
OPEN cc FOR PC$Select ; RETURN cc ; END
; / |
q The client side
request:
SQL> set serveroutput on SQL> DECLARE
2 cur SYS_REFCURSOR ;
3 rec EMP%ROWTYPE ;
4 BEGIN
5 cur := Return_Cursor(
'SELECT * FROM EMP WHERE DEPTNO=10' ) ;
6 LOOP
7 FETCH cur INTO rec ;
8 EXIT WHEN cur%NOTFOUND ;
9 dbms_output.put_line(
rec.ENAME ) ; 10 END LOOP ; 11 CLOSE cur ; 12 END; 13
14 / CLARK KING MILLER Procédure PL/SQL terminée avec succès. SQL> |
CallableStatement call = conn.prepareCall ("{ ? = call
Return_Cursor (?)}");
call.registerOutParameter (1, OracleTypes.CURSOR);
call.setString (2, "SELECT * FROM EMP WHERE DEPTNO=10");
call.execute ();
ResultSet rset2 = (ResultSet)call.getObject (1);
while (rset2.next ())
{
System.out.println( "Ename = " + rset2.getString(2) ) ;
} |
q The database package:
CREATE OR REPLACE PACKAGE Pkg_CurIS …… -- EMP Record -- TYPE R_EMP IS RECORD ( EMPNO
EMP.EMPNO%TYPE, ENAME
EMP.ENAME%TYPE, JOB EMP.JOB%TYPE, MGR EMP.MGR%TYPE, HIREDATE EMP.HIREDATE%TYPE, SAL EMP.SAL%TYPE, COMM EMP.COMM%TYPE,
DEPTNO
EMP.DEPTNO%TYPE ); -- Cursor
returning EMP record -- TYPE TP_CUR IS REF CURSOR RETURN R_EMP ; …… FUNCTION Get_Raws3 RETURN TP_CUR ; END Pkg_Cur
; / |
CREATE OR REPLACE PACKAGE BODY Pkg_CurIS … … FUNCTION Get_Raws3 RETURN TP_CUR IS Cur TP_CUR ; BEGIN OPEN Cur FOR SELECT *
FROM EMP ; RETURN Cur ;
END ;
END Pkg_Cur ; / |
q The client side
request:
SQL> DECLARE
2 cur Pkg_Cur.TP_CUR ;
3 rec EMP%ROWTYPE ;
4 BEGIN
5 cur := Pkg_Cur.Get_Raws3 ;
6 LOOP
7 FETCH cur INTO rec ;
8 EXIT WHEN cur%NOTFOUND ;
9 dbms_output.put_line(
rec.EMPNO || ' ' ||rec.ENAME ) ; 10 END LOOP ; 11 CLOSE cur ; 12 END; 13 / 7369 SMITH 7499 ALLEN 7521 WARD 7566 JONES 7654 MARTIN 7698 BLAKE 7782 CLARK 7788 SCOTT 7839 KING 7844 TURNER 7876 ADAMS 7900 JAMES 7902
FORD 7934
MILLER Procédure
PL/SQL terminée avec succès. SQL> |
CallableStatement call = conn.prepareCall ("{ ? = call
Pkg_Cur.Get_Raws3 ()}");
call.registerOutParameter (1, OracleTypes.CURSOR);
call.execute ();
ResultSet rset = (ResultSet)call.getObject (1);
while (rset.next ())
{
System.out.println( “Ename = “ + rset.getString(2) ) ;
} |
q The database types:
CREATE OR REPLACE TYPE
TYP_REC_EMP AS OBJECT ( EMPNO NUMBER(4), ENAME VARCHAR2(10), JOB VARCHAR2(9), MGR NUMBER(4),
HIREDATE DATE, SAL
NUMBER(7,2), COMM
NUMBER(7,2), DEPTNO
NUMBER(2) ) / CREATE OR REPLACE TYPE TYP_TAB_REC_EMP AS TABLE OF
TYP_REC_EMP / |
q The database package:
CREATE OR REPLACE PACKAGE
Pkg_Cur IS TYPE REC_EMP IS TABLE OF EMP%ROWTYPE INDEX BY BINARY_INTEGER ; FUNCTION Get_Raws RETURN REC_EMP ; FUNCTION Get_Raws2 ( cur_lig IN SYS_REFCURSOR ) RETURN TYP_TAB_REC_EMP PIPELINED ; END Pkg_Cur
; / |
CREATE OR REPLACE PACKAGE
BODY Pkg_Cur IS
FUNCTION Get_Raws RETURN REC_EMP IS TAB REC_EMP ; BEGIN
SELECT * BULK COLLECT INTO TAB FROM EMP
; RETURN TAB ; END ; FUNCTION Get_Raws2 ( cur_lig IN
SYS_REFCURSOR ) RETURN TYP_TAB_REC_EMP PIPELINED IS Trec
TYP_REC_EMP := TYP_REC_EMP(NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL ) ; Remp
EMP%ROWTYPE ; BEGIN LOOP FETCH cur_lig INTO Remp ; EXIT WHEN cur_lig%NOTFOUND ; -- Handling
datas -- Trec.EMPNO := Remp.EMPNO ; Trec.ENAME := Remp.ENAME ; Trec.JOB := Remp.JOB ; Trec.MGR := Remp.MGR ; Trec.HIREDATE := Remp.HIREDATE ; Trec.SAL := Remp.SAL * 1.1 ; Trec.COMM := Remp.COMM ; Trec.DEPTNO :=
Remp.DEPTNO ; -- Return
value -- PIPE ROW( Trec ) ; END LOOP ; RETURN ; END ; END Pkg_Cur
; / |
q The client side
request:
SQL> set linesize 200 SQL> SQL> SELECT * FROM
2
TABLE(Pkg_Cur.Get_Raws2(CURSOR(SELECT * FROM EMP WHERE DEPTNO = 10)))
3 /
EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO ---------- ---------- ---------
---------- -------- ---------- ---------- ----------
7782 CLARK MANAGER 7839 09/06/81 2695 10
7839 KING PRESIDENT 17/12/80
5500 10
7934 MILLER CLERK 7782 09/12/82 1430 10 SQL> |
// Select columns from the
EMP table ResultSet rset = stmt.executeQuery ( "SELECT * FROM
TABLE(Pkg_Cur.Get_Raws2(CURSOR(SELECT * FROM EMP WHERE DEPTNO = 10)))"); // Iterate through the
result and print the employee names while (rset.next ())
System.out.println (rset.getString (2)); |