Search This Blog

EXIT WHEN cursor%NOTFOUND

Environment: Oracle 10g
A very simple concept, but if overlooked; very painful, and hard to debug:
     EXIT WHEN cursor%NOTFOUND;

Problem:
Say we are iterating on a cursor, how we may write exit statement ?
Lets say cursor is 'my_cur'

We may write code like:
OPEN my_cur;
LOOP
     FETCH my_cur
     INTO my_cur_record;
     EXIT WHEN my_cur%NOTFOUND; --Exit Condition
     --
     -- PROCESS THE CURSOR DATA.
     --
END LOOP;
--close the cursor.

If there are 2500 rows in cursor, program will iterate in this loop for 2500 times.

Lets say to increase performance, above written legacy code is changed and rows are fetched in batches of 1000 rows.We may end up with something like this:
OPEN my_cur; 
LOOP
     FETCH my_cur
     BULK COLLECT INTO my_cur_table
     LIMIT 1000;
     EXIT WHEN my_cur%NOTFOUND; --Exit Condition:
     --
     -- PROCESS THE 1000 rows fetched. DATA.
     --
END LOOP;
--close the cursor.

Apparently this code seems to be 100% correct, and developer expects that
  • in first iteration it will fetch 1000 rows
  • then in second iteration; next 1000 rows (total 2000 rows)
  • and in last iteration rest of 500 rows.
But actually this code will only process 2000 rows and will leave last 500 rows... Why?
Answer is simple:
  • my_cur%NOTFOUND; = TRUE (If 'number of fetched rows' is exactly equals to 'batch limt') [In our case batch limit = 1000]
  • my_cur%NOTFOUND; = FALSE (If 'number of fetched rows' is NOT exactly equals to 'batch limt') [In our case batch limit = 1000]
Solution:
Solutions is even simplest,
Instead of checking %NOTFOUND condition with cursor, simply check that if fetched rows = 0, then exit, i.e.:
     EXIT WHEN my_cur_table.COUNT = 0;




Comments/ Questions are welcomed...


1 comment: