Reputation: 15876
Is there an easier way to close all open cursors from within a PL/SQL program (Oracle 10G).
I have a program which can generate a number of exceptions. To exit properly, i need to check whether there are any cursors open and close them. This is the kind of situation i am ending up with.
Procedure test
is
--
---
Begin
--
--
Exception
when no_data_found then
if cursorA%isopen close
if cursorB%isopen close
if cursorC%isopen close
when invalid_date then
if cursorA%isopen close
if cursorB%isopen close
if cursorC%isopen close
when invalid_user then
if cursorA%isopen close
if cursorB%isopen close
if cursorC%isopen close
when others then
if cursorA%isopen close
if cursorB%isopen close
if cursorC%isopen close
End test;
Obviously the above is not ideal especially if there are many exception clauses. Instead of havin the same checks on each exception block, is there a quicker way to close all open cursor? Note: It needs to close only the cursors opened by the currently running pl/sql program because there could be other pl/sql program that could also open cursors.
Thanks in advance
Upvotes: 2
Views: 30811
Reputation: 231661
Are you sure that you need to use the explicit cursor syntax in the first place rather than using implicit cursors? If you use implicit cursors, Oracle takes care of opening and closing them automatically. You can declare the query inline or out of line as in the block below
DECLARE
CURSOR cursor_a
IS SELECT *
FROM emp;
BEGIN
FOR a IN cursor_a
LOOP
<<do something>>
END LOOP;
FOR b IN (SELECT *
FROM dept)
LOOP
<<do something else>>
END LOOP;
END;
In either case, Oracle will automatically take care of closing the cursor when you exit the block.
If you do need to use explicit cursors for some reason, and assuming that you need to catch multiple different exceptions because you will handle those exceptions differently, you can create a nested block that closes the cursors and just call that from each exception handler
DECLARE
CURSOR cursor_a
IS SELECT *
FROM emp;
CURSOR cursor_b
IS SELECT *
FROM dept;
PROCEDURE close_open_cursors
AS
BEGIN
IF( cursor_a%isopen )
THEN
close cursor_a;
END IF;
IF( cursor_b%isopen )
THEN
close cursor_b;
END IF;
END;
BEGIN
OPEN cursor_a;
OPEN cursor_b;
RAISE no_data_found;
EXCEPTION
WHEN no_data_found
THEN
close_open_cursors;
<<do something meaningful>>
WHEN too_many_rows
THEN
close_open_cursors;
<<do something meaningful>>
WHEN others
THEN
close_open_cursors;
raise;
END;
Upvotes: 12