Table of Contents
How to fetch data from ref cursor in Oracle using for loop?
We will examine different ways to fetch data from ref cursor.
We will use SYS_REFCURSOR as ref cursor variable as its a week type of cursor.
It will allow us to fetch data as per our format.
Fetching data from ref cursor using a plsql block:
Using simple plsql variable:
First we will use simple plsql variable to fetch data from a ref cursor.
--How to fetch data from ref cursor in Oracle using for loop? : Example SET SERVEROUTPUT ON; DECLARE V_EMPLOYEE_ID EMPLOYEES.EMPLOYEE_ID%TYPE := NULL; V_FIRST_NAME EMPLOYEES.FIRST_NAME%TYPE := NULL; V_LAST_NAME EMPLOYEES.LAST_NAME%TYPE := NULL; V_SALARY EMPLOYEES.SALARY%TYPE := NULL; V_JOB_ID EMPLOYEES.JOB_ID%TYPE := NULL; -- V_CURSOR SYS_REFCURSOR; BEGIN OPEN V_CURSOR FOR SELECT EMPLOYEE_ID, FIRST_NAME, LAST_NAME, SALARY, JOB_ID FROM EMPLOYEES WHERE DEPARTMENT_ID = 30; -- LOOP FETCH V_CURSOR INTO V_EMPLOYEE_ID, V_FIRST_NAME, V_LAST_NAME, V_SALARY, V_JOB_ID; EXIT WHEN V_CURSOR%NOTFOUND; DBMS_OUTPUT.PUT_LINE('EMPLOYEE -> ID -> '||V_EMPLOYEE_ID||' -> NAME -> '||V_FIRST_NAME||' '||V_LAST_NAME||' - > SALARY -> '||V_SALARY||' -> JOB_ID ->'||V_JOB_ID); END LOOP; CLOSE V_CURSOR; END; /
--How to fetch data from ref cursor in Oracle using for loop? : Output PL/SQL procedure successfully completed. EMPLOYEE -> ID -> 208 -> NAME -> Jhon Smith - > SALARY -> 1000 -> JOB_ID ->PU_CLERK EMPLOYEE -> ID -> 114 -> NAME -> Den Raphaely - > SALARY -> 11000 -> JOB_ID ->PU_MAN EMPLOYEE -> ID -> 115 -> NAME -> Alexander Khoo - > SALARY -> 3100 -> JOB_ID ->PU_CLERK EMPLOYEE -> ID -> 116 -> NAME -> Shelli Baida - > SALARY -> 2900 -> JOB_ID ->PU_CLERK EMPLOYEE -> ID -> 117 -> NAME -> Sigal Tobias - > SALARY -> 2800 -> JOB_ID ->PU_CLERK EMPLOYEE -> ID -> 118 -> NAME -> Guy Himuro - > SALARY -> 2600 -> JOB_ID ->PU_CLERK EMPLOYEE -> ID -> 119 -> NAME -> Karen Colmenares - > SALARY -> 2500 -> JOB_ID ->PU_CLERK
Extracting data using plsql record variable:
Now using record variable to fetch data from a ref cursor:
--How to fetch data from ref cursor in Oracle using for loop? : Example DECLARE TYPE T_REC IS RECORD (EMPLOYEE_ID EMPLOYEES.EMPLOYEE_ID%TYPE, FIRST_NAME EMPLOYEES.FIRST_NAME%TYPE, LAST_NAME EMPLOYEES.LAST_NAME%TYPE, SALARY EMPLOYEES.SALARY%TYPE, JOB_ID EMPLOYEES.JOB_ID%TYPE ); -- V_REC T_REC; -- V_CURSOR SYS_REFCURSOR; BEGIN OPEN V_CURSOR FOR SELECT EMPLOYEE_ID, FIRST_NAME, LAST_NAME, SALARY, JOB_ID FROM EMPLOYEES WHERE DEPARTMENT_ID = 30; -- LOOP FETCH V_CURSOR INTO V_REC; EXIT WHEN V_CURSOR%NOTFOUND; DBMS_OUTPUT.PUT_LINE('EMPLOYEE -> ID -> '||V_REC.EMPLOYEE_ID||' -> NAME -> '||V_REC.FIRST_NAME||' '||V_REC.LAST_NAME||' - > SALARY -> '||V_REC.SALARY||' -> JOB_ID ->'||V_REC.JOB_ID); END LOOP; CLOSE V_CURSOR; END; /
--How to fetch data from ref cursor in Oracle using for loop? : Output PL/SQL procedure successfully completed. EMPLOYEE -> ID -> 208 -> NAME -> Jhon Smith - > SALARY -> 1000 -> JOB_ID ->PU_CLERK EMPLOYEE -> ID -> 114 -> NAME -> Den Raphaely - > SALARY -> 11000 -> JOB_ID ->PU_MAN EMPLOYEE -> ID -> 115 -> NAME -> Alexander Khoo - > SALARY -> 3100 -> JOB_ID ->PU_CLERK EMPLOYEE -> ID -> 116 -> NAME -> Shelli Baida - > SALARY -> 2900 -> JOB_ID ->PU_CLERK EMPLOYEE -> ID -> 117 -> NAME -> Sigal Tobias - > SALARY -> 2800 -> JOB_ID ->PU_CLERK EMPLOYEE -> ID -> 118 -> NAME -> Guy Himuro - > SALARY -> 2600 -> JOB_ID ->PU_CLERK EMPLOYEE -> ID -> 119 -> NAME -> Karen Colmenares - > SALARY -> 2500 -> JOB_ID ->PU_CLERK
Fetching data Using collection:
Using collection to fetch data from ref cursor:
--How to fetch data from ref cursor in Oracle using for loop? : Example DECLARE TYPE T_REC IS RECORD (EMPLOYEE_ID EMPLOYEES.EMPLOYEE_ID%TYPE, FIRST_NAME EMPLOYEES.FIRST_NAME%TYPE, LAST_NAME EMPLOYEES.LAST_NAME%TYPE, SALARY EMPLOYEES.SALARY%TYPE, JOB_ID EMPLOYEES.JOB_ID%TYPE ); -- TYPE T_REFTAB IS TABLE OF T_REC INDEX BY PLS_INTEGER; V_REFTAB T_REFTAB; -- V_CURSOR SYS_REFCURSOR; BEGIN OPEN V_CURSOR FOR SELECT EMPLOYEE_ID, FIRST_NAME, LAST_NAME, SALARY, JOB_ID FROM EMPLOYEES WHERE DEPARTMENT_ID = 30; -- FETCH V_CURSOR BULK COLLECT INTO V_REFTAB; FOR I IN 1..V_REFTAB.COUNT LOOP DBMS_OUTPUT.PUT_LINE('EMPLOYEE -> ID -> '||V_REFTAB(I).EMPLOYEE_ID||' -> NAME -> '||V_REFTAB(I).FIRST_NAME||' '||V_REFTAB(I).LAST_NAME||' - > SALARY -> '||V_REFTAB(I).SALARY||' -> JOB_ID ->'||V_REFTAB(I).JOB_ID); END LOOP; CLOSE V_CURSOR; END; /
--How to fetch data from ref cursor in Oracle using for loop? : Output PL/SQL procedure successfully completed. EMPLOYEE -> ID -> 208 -> NAME -> Jhon Smith - > SALARY -> 1000 -> JOB_ID ->PU_CLERK EMPLOYEE -> ID -> 114 -> NAME -> Den Raphaely - > SALARY -> 11000 -> JOB_ID ->PU_MAN EMPLOYEE -> ID -> 115 -> NAME -> Alexander Khoo - > SALARY -> 3100 -> JOB_ID ->PU_CLERK EMPLOYEE -> ID -> 116 -> NAME -> Shelli Baida - > SALARY -> 2900 -> JOB_ID ->PU_CLERK EMPLOYEE -> ID -> 117 -> NAME -> Sigal Tobias - > SALARY -> 2800 -> JOB_ID ->PU_CLERK EMPLOYEE -> ID -> 118 -> NAME -> Guy Himuro - > SALARY -> 2600 -> JOB_ID ->PU_CLERK EMPLOYEE -> ID -> 119 -> NAME -> Karen Colmenares - > SALARY -> 2500 -> JOB_ID ->PU_CLERK
Usage of BULK COLLECT and FORALL:
Using BULK COLLECT and FORALL to fetch data from a ref cursor:
Creating a test table to test the BULK COLLECT and FORALL scenario. As we know that for FORALL DML is mandatory. So we will insert data into test table.
CREATE TABLE EMPLOYEES_REF_TEST AS SELECT EMPLOYEE_ID, FIRST_NAME, LAST_NAME, SALARY, JOB_ID FROM EMPLOYEES WHERE 1 = 2;
--How to fetch data from ref cursor in Oracle using for loop? : Example DECLARE TYPE T_REC IS RECORD (EMPLOYEE_ID EMPLOYEES.EMPLOYEE_ID%TYPE, FIRST_NAME EMPLOYEES.FIRST_NAME%TYPE, LAST_NAME EMPLOYEES.LAST_NAME%TYPE, SALARY EMPLOYEES.SALARY%TYPE, JOB_ID EMPLOYEES.JOB_ID%TYPE ); -- TYPE T_REFTAB IS TABLE OF T_REC INDEX BY PLS_INTEGER; V_REFTAB T_REFTAB; -- V_CURSOR SYS_REFCURSOR; BEGIN OPEN V_CURSOR FOR SELECT EMPLOYEE_ID, FIRST_NAME, LAST_NAME, SALARY, JOB_ID FROM EMPLOYEES WHERE DEPARTMENT_ID = 30; -- FETCH V_CURSOR BULK COLLECT INTO V_REFTAB; FORALL I IN 1..V_REFTAB.COUNT INSERT INTO EMPLOYEES_REF_TEST(EMPLOYEE_ID, FIRST_NAME, LAST_NAME, SALARY, JOB_ID ) VALUES(V_REFTAB(I).EMPLOYEE_ID, V_REFTAB(I).FIRST_NAME, V_REFTAB(I).LAST_NAME, V_REFTAB(I).SALARY, V_REFTAB(I).JOB_ID ); CLOSE V_CURSOR; -- FOR I IN (SELECT * FROM EMPLOYEES_REF_TEST) LOOP DBMS_OUTPUT.PUT_LINE('EMPLOYEE -> ID -> '||I.EMPLOYEE_ID||' -> NAME -> '||I.FIRST_NAME||' '||I.LAST_NAME||' - > SALARY -> '||I.SALARY||' -> JOB_ID ->'||I.JOB_ID); END LOOP; END; /
--How to fetch data from ref cursor in Oracle using for loop? : Output PL/SQL procedure successfully completed. EMPLOYEE -> ID -> 208 -> NAME -> Jhon Smith - > SALARY -> 1000 -> JOB_ID ->PU_CLERK EMPLOYEE -> ID -> 114 -> NAME -> Den Raphaely - > SALARY -> 11000 -> JOB_ID ->PU_MAN EMPLOYEE -> ID -> 115 -> NAME -> Alexander Khoo - > SALARY -> 3100 -> JOB_ID ->PU_CLERK EMPLOYEE -> ID -> 116 -> NAME -> Shelli Baida - > SALARY -> 2900 -> JOB_ID ->PU_CLERK EMPLOYEE -> ID -> 117 -> NAME -> Sigal Tobias - > SALARY -> 2800 -> JOB_ID ->PU_CLERK EMPLOYEE -> ID -> 118 -> NAME -> Guy Himuro - > SALARY -> 2600 -> JOB_ID ->PU_CLERK EMPLOYEE -> ID -> 119 -> NAME -> Karen Colmenares - > SALARY -> 2500 -> JOB_ID ->PU_CLERK
Fetching data from ref cursor using a stored procedure:
Using simple procedure:
First we will create a table for exception handling:
CREATE TABLE EMP_SAVE_EXCEPTION_TAB ( ERROR_ID NUMBER GENERATED ALWAYS AS IDENTITY, ERROR_CODE VARCHAR2(1000), ERROR_MSG VARCHAR2(4000), ERROR_DATE DATE );
Simple format of procedure:
--How to fetch data from ref cursor in Oracle using for loop? : Example CREATE OR REPLACE PROCEDURE SP_REF_CUR_TEST(P_DEPTNO DEPARTMENTS.DEPARTMENT_ID%TYPE) IS TYPE T_REC IS RECORD (EMPLOYEE_ID EMPLOYEES.EMPLOYEE_ID%TYPE, FIRST_NAME EMPLOYEES.FIRST_NAME%TYPE, LAST_NAME EMPLOYEES.LAST_NAME%TYPE, SALARY EMPLOYEES.SALARY%TYPE, JOB_ID EMPLOYEES.JOB_ID%TYPE ); -- TYPE T_REFTAB IS TABLE OF T_REC INDEX BY PLS_INTEGER; V_REFTAB T_REFTAB; -- V_CURSOR SYS_REFCURSOR; BEGIN OPEN V_CURSOR FOR SELECT EMPLOYEE_ID, FIRST_NAME, LAST_NAME, SALARY, JOB_ID FROM EMPLOYEES WHERE DEPARTMENT_ID = P_DEPTNO; -- FETCH V_CURSOR BULK COLLECT INTO V_REFTAB; FOR I IN 1..V_REFTAB.COUNT LOOP DBMS_OUTPUT.PUT_LINE('EMPLOYEE -> ID -> '||V_REFTAB(I).EMPLOYEE_ID||' -> NAME -> '||V_REFTAB(I).FIRST_NAME||' '||V_REFTAB(I).LAST_NAME||' - > SALARY -> '||V_REFTAB(I).SALARY||' -> JOB_ID ->'||V_REFTAB(I).JOB_ID); END LOOP; CLOSE V_CURSOR; END; /
EXEC SP_REF_CUR_TEST(30);
--How to fetch data from ref cursor in Oracle using for loop? : Output PL/SQL procedure successfully completed. EMPLOYEE -> ID -> 208 -> NAME -> Jhon Smith - > SALARY -> 1000 -> JOB_ID ->PU_CLERK EMPLOYEE -> ID -> 114 -> NAME -> Den Raphaely - > SALARY -> 11000 -> JOB_ID ->PU_MAN EMPLOYEE -> ID -> 115 -> NAME -> Alexander Khoo - > SALARY -> 3100 -> JOB_ID ->PU_CLERK EMPLOYEE -> ID -> 116 -> NAME -> Shelli Baida - > SALARY -> 2900 -> JOB_ID ->PU_CLERK EMPLOYEE -> ID -> 117 -> NAME -> Sigal Tobias - > SALARY -> 2800 -> JOB_ID ->PU_CLERK EMPLOYEE -> ID -> 118 -> NAME -> Guy Himuro - > SALARY -> 2600 -> JOB_ID ->PU_CLERK EMPLOYEE -> ID -> 119 -> NAME -> Karen Colmenares - > SALARY -> 2500 -> JOB_ID ->PU_CLERK
Using collection:
Complex format of procedure:
CREATE OR REPLACE PROCEDURE SP_REF_CUR_TEST(P_DEPTNO DEPARTMENTS.DEPARTMENT_ID%TYPE) IS TYPE T_REC IS RECORD (EMPLOYEE_ID EMPLOYEES.EMPLOYEE_ID%TYPE, FIRST_NAME EMPLOYEES.FIRST_NAME%TYPE, LAST_NAME EMPLOYEES.LAST_NAME%TYPE, SALARY EMPLOYEES.SALARY%TYPE, JOB_ID EMPLOYEES.JOB_ID%TYPE ); -- TYPE T_REFTAB IS TABLE OF T_REC INDEX BY PLS_INTEGER; V_REFTAB T_REFTAB; -- V_CURSOR SYS_REFCURSOR; V_ERROR_CODE VARCHAR2(100); V_ERROR_INDEX VARCHAR2(100); -- PROCEDURE SP_SAVE_EXCEPTION_PROC (P_ERROR_CODE VARCHAR2, P_ERROR_MSG VARCHAR2, P_ERROR_DATE DATE ) IS PRAGMA AUTONOMOUS_TRANSACTION; BEGIN INSERT INTO EMP_SAVE_EXCEPTION_TAB(ERROR_CODE, ERROR_MSG, ERROR_DATE) VALUES(P_ERROR_CODE, P_ERROR_MSG, P_ERROR_DATE); -- COMMIT; END SP_SAVE_EXCEPTION_PROC; BEGIN DELETE EMPLOYEES_REF_TEST; -- OPEN V_CURSOR FOR SELECT EMPLOYEE_ID, FIRST_NAME, LAST_NAME, SALARY, JOB_ID FROM EMPLOYEES WHERE DEPARTMENT_ID = P_DEPTNO; -- LOOP FETCH V_CURSOR BULK COLLECT INTO V_REFTAB LIMIT 50; EXIT WHEN V_REFTAB.COUNT = 0; BEGIN FORALL I IN 1..V_REFTAB.COUNT SAVE EXCEPTIONS INSERT INTO EMPLOYEES_REF_TEST(EMPLOYEE_ID, FIRST_NAME, LAST_NAME, SALARY, JOB_ID ) VALUES(V_REFTAB(I).EMPLOYEE_ID, V_REFTAB(I).FIRST_NAME, V_REFTAB(I).LAST_NAME, V_REFTAB(I).SALARY, V_REFTAB(I).JOB_ID ); EXCEPTION WHEN OTHERS THEN IF SQLCODE = -24381 THEN FOR I IN 1..SQL%BULK_EXCEPTIONS.COUNT LOOP V_ERROR_CODE := SQL%BULK_EXCEPTIONS(I).ERROR_CODE; V_ERROR_INDEX := SQL%BULK_EXCEPTIONS(I).ERROR_INDEX; SP_SAVE_EXCEPTION_PROC(V_ERROR_CODE, 'ERROR AT INDEX NO -> '||V_ERROR_INDEX||' -> '||SQLERRM(V_ERROR_CODE), SYSDATE); END LOOP; ELSE SP_SAVE_EXCEPTION_PROC(SQLCODE, SQLERRM, SYSDATE); END IF; END; END LOOP; CLOSE V_CURSOR; -- FOR I IN (SELECT * FROM EMPLOYEES_REF_TEST) LOOP DBMS_OUTPUT.PUT_LINE('EMPLOYEE -> ID -> '||I.EMPLOYEE_ID||' -> NAME -> '||I.FIRST_NAME||' '||I.LAST_NAME||' - > SALARY -> '||I.SALARY||' -> JOB_ID ->'||I.JOB_ID); END LOOP; EXCEPTION WHEN OTHERS THEN SP_SAVE_EXCEPTION_PROC(SQLCODE, 'ERROR AT THE END -> '||DBMS_UTILITY.FORMAT_ERROR_BACKTRACE, SYSDATE); END; /
EXEC SP_REF_CUR_TEST(30);
PL/SQL procedure successfully completed. EMPLOYEE -> ID -> 208 -> NAME -> Jhon Smith - > SALARY -> 1000 -> JOB_ID ->PU_CLERK EMPLOYEE -> ID -> 114 -> NAME -> Den Raphaely - > SALARY -> 11000 -> JOB_ID ->PU_MAN EMPLOYEE -> ID -> 115 -> NAME -> Alexander Khoo - > SALARY -> 3100 -> JOB_ID ->PU_CLERK EMPLOYEE -> ID -> 116 -> NAME -> Shelli Baida - > SALARY -> 2900 -> JOB_ID ->PU_CLERK EMPLOYEE -> ID -> 117 -> NAME -> Sigal Tobias - > SALARY -> 2800 -> JOB_ID ->PU_CLERK EMPLOYEE -> ID -> 118 -> NAME -> Guy Himuro - > SALARY -> 2600 -> JOB_ID ->PU_CLERK EMPLOYEE -> ID -> 119 -> NAME -> Karen Colmenares - > SALARY -> 2500 -> JOB_ID ->PU_CLERK
Fetching data from ref cursor using a stored function:
CREATE OR REPLACE FUNCTION FUN_REF_CUR_TEST(P_DEPTNO DEPARTMENTS.DEPARTMENT_ID%TYPE) RETURN SYS_REFCURSOR IS TYPE T_REC IS RECORD (EMPLOYEE_ID EMPLOYEES.EMPLOYEE_ID%TYPE, FIRST_NAME EMPLOYEES.FIRST_NAME%TYPE, LAST_NAME EMPLOYEES.LAST_NAME%TYPE, SALARY EMPLOYEES.SALARY%TYPE, JOB_ID EMPLOYEES.JOB_ID%TYPE ); -- TYPE T_REFTAB IS TABLE OF T_REC INDEX BY PLS_INTEGER; V_REFTAB T_REFTAB; -- V_CURSOR SYS_REFCURSOR; BEGIN OPEN V_CURSOR FOR SELECT EMPLOYEE_ID, FIRST_NAME, LAST_NAME, SALARY, JOB_ID FROM EMPLOYEES WHERE DEPARTMENT_ID = P_DEPTNO; -- RETURN V_CURSOR; CLOSE V_CURSOR; EXCEPTION WHEN OTHERS THEN RETURN NULL; END; /
DECLARE V_EMPLOYEE_ID EMPLOYEES.EMPLOYEE_ID%TYPE := NULL; V_FIRST_NAME EMPLOYEES.FIRST_NAME%TYPE := NULL; V_LAST_NAME EMPLOYEES.LAST_NAME%TYPE := NULL; V_SALARY EMPLOYEES.SALARY%TYPE := NULL; V_JOB_ID EMPLOYEES.JOB_ID%TYPE := NULL; -- V_CUR SYS_REFCURSOR; BEGIN V_CUR := FUN_REF_CUR_TEST(30); LOOP FETCH V_CUR INTO V_EMPLOYEE_ID, V_FIRST_NAME, V_LAST_NAME, V_SALARY, V_JOB_ID; -- EXIT WHEN V_CUR%NOTFOUND; DBMS_OUTPUT.PUT_LINE('EMPLOYEE -> ID -> '||V_EMPLOYEE_ID||' -> NAME -> '||V_FIRST_NAME||' '||V_LAST_NAME||' - > SALARY -> '||V_SALARY||' -> JOB_ID ->'||V_JOB_ID); END LOOP; EXCEPTION WHEN OTHERS THEN DBMS_OUTPUT.PUT_LINE('ERROR - > '||SQLERRM); END; /
RELATED TOPICS: