This page is based on examples to be easier to follow. To explain better the Oracle Fetch Bulk Collect operator with using a limit we need to show the based data as is. The following SQL return 10 rows with ID value from 1st to 10. Take a look at the query and the output below.
SELECT rownum AS ID FROM DUAL CONNECT BY rownum < 11;
Image may be NSFW.
Clik here to view.
The following Online Tech Support tutorial examples have written using the ID values above and the first PL/SQL block is taken from somebody’s code. Do NOT write the code as following:
DECLARE -- Declare cursor CURSOR c_my_dual IS SELECT rownum AS ID FROM DUAL CONNECT BY rownum < 11; -- Declare record type TYPE r_my_dual IS TABLE OF c_my_dual%rowtype; -- Declare array collection type t_my_dual r_my_dual; BEGIN -- Open the cursor OPEN c_my_dual; LOOP -- Fetch the data as bulk collection into the t_my_dual and limit has set to 3 rows FETCH c_my_dual BULK COLLECT INTO t_my_dual LIMIT 3; EXIT WHEN c_my_dual%NOTFOUND; END LOOP; -- Close the cursor CLOSE c_my_dual; -- If collection is empty then skip following IF t_my_dual.FIRST IS NULL THEN DBMS_OUTPUT.PUT_LINE('>Exit: the Collection is Empty.'); RETURN; END IF; -- Send to output the collection values FOR i IN t_my_dual.FIRST .. t_my_dual.LAST LOOP DBMS_OUTPUT.PUT_LINE('ID => ' || t_my_dual(i).ID); END LOOP; END;
Image may be NSFW.
Clik here to view.
This “bad” code is returning only the last buffer from the collection and not all values. Let’s have a look at code and what does it do. The DECLARE block part we did declare cursor “c_my_dual” using the first example SQL query and to cursor associative record array type “r_my_dual” and on top the last type a table variable “t_my_dual“.
Now between BEGIN and END keyword we are opening the “c_my_dual” cursor. The second block is a loop to fetch data from the SQL into variable “t_my_dual” as “bulk collect”; since the limit has set to “3” rows the FETCH will be executed 4 times for 10 rows. The main problem with this code is that the rest of activities are left out from this loop and “BULK COLLECT” keyword clearing up the variable before starting to use the variable. This is the reason why the second and last loop shows only the 10th ID – this is the fourth bulk of data only one value of possible three. Coming back to the first loop we are closing the opened cursor “c_my_dual” after the loop is done. The following IF-block is checking that we do not have an empty collection and if this is true the block sends message “>Exit: the Collection is Empty.” and skips the following using the RETURN function. If the collection was not empty the last LOOP will be executed it shows all rows from first to last in dbms output. One more time DO NOT USE the code above for your programming and instead you could use the next one below.
The following block is almost the same code only with small but important changes. The last LOOP statement is inside the 1st LOOP block and we are not skipping the second loop with RETURN but EXIT keyword.
DECLARE -- Declare cursor CURSOR c_my_dual IS SELECT rownum AS ID FROM DUAL CONNECT BY rownum < 11; -- Declare record type TYPE r_my_dual IS TABLE OF c_my_dual%rowtype; -- Declare array collection type t_my_dual r_my_dual; BEGIN -- Open the cursor OPEN c_my_dual; LOOP -- Fetch the data as bulk collection into the t_my_dual and limit has set to 3 rows FETCH c_my_dual BULK COLLECT INTO t_my_dual LIMIT 3; -- If collection is empty then skip following IF t_my_dual.FIRST IS NULL THEN DBMS_OUTPUT.PUT_LINE('>Exit: the Collection is Empty.'); EXIT; END IF; -- Send to output the collection values FOR i IN t_my_dual.FIRST .. t_my_dual.LAST LOOP DBMS_OUTPUT.PUT_LINE('ID => ' || t_my_dual(i).ID); END LOOP; EXIT WHEN c_my_dual%NOTFOUND; END LOOP; -- Close the cursor CLOSE c_my_dual; END;
Image may be NSFW.
Clik here to view.
Now the last output shows all ID values as the first query had. The last example of PL/SQL block is written to try out the IF statement and to do we have decreased the BULK COLLECT limit to 2 rows. The last execution of the 1st LOOP is an empty run and as the output below shows the last message is coming from the IF statement “>Exit: the Collection is Empty.“.
DECLARE -- Declare cursor CURSOR c_my_dual IS SELECT rownum AS ID FROM DUAL CONNECT BY rownum < 11; -- Declare record type TYPE r_my_dual IS TABLE OF c_my_dual%rowtype; -- Declare array collection type t_my_dual r_my_dual; BEGIN -- Open the cursor OPEN c_my_dual; LOOP -- Fetch the data as bulk collection into the t_my_dual and limit has set to 3 rows FETCH c_my_dual BULK COLLECT INTO t_my_dual LIMIT 2; -- If collection is empty then skip following IF t_my_dual.FIRST IS NULL THEN DBMS_OUTPUT.PUT_LINE('>Exit: the Collection is Empty.'); EXIT; END IF; -- Send to output the collection values FOR i IN t_my_dual.FIRST .. t_my_dual.LAST LOOP DBMS_OUTPUT.PUT_LINE('ID => ' || t_my_dual(i).ID); END LOOP; EXIT WHEN c_my_dual%NOTFOUND; END LOOP; -- Close the cursor CLOSE c_my_dual; END;
Image may be NSFW.
Clik here to view.
You can read more about PL/SQL Collections and Records on this link.
See Also:
Online Tech Support Home