PL/SQL has the ability to close the (locally declared) open cursors, once they go out of referencing PL/SQL unit -not sure when this feature got introduced in PL/SQL.
demo@ORA12C> create or replace package demo_pkg
2 as
3 procedure p;
4 end;
5 /
Package created.
demo@ORA12C> create or replace package body demo_pkg
2 as
3 cursor c is select * from dual;
4 r c%rowtype;
5 procedure p1 as
6 begin
7 open c;
8 fetch c into r;
9 end p1;
10
11 procedure p as
12 begin
13 for i in 1..5000
14 loop
15 p1;
16 end loop;
17 end;
18 end;
19 /
Package body created.
demo@ORA12C>
demo@ORA12C> exec demo_pkg.p;
BEGIN demo_pkg.p; END;
*
ERROR at line 1:
ORA-06511: PL/SQL: cursor already open
ORA-06512: at "DEMO.DEMO_PKG", line 3
ORA-06512: at "DEMO.DEMO_PKG", line 7
ORA-06512: at "DEMO.DEMO_PKG", line 15
ORA-06512: at line 1
With a slight tweek in the package body, it still get this error.
demo@ORA12C> create or replace package body demo_pkg
2 as
3 cursor c is select * from dual;
4 r c%rowtype;
5 procedure p as
6 begin
7 open c;
8 fetch c into r;
9 end;
10 end;
11 /
Package body created.
demo@ORA12C> begin
2 for i in 1..5000
3 loop
4 demo_pkg.p;
5 end loop;
6 end;
7 /
begin
*
ERROR at line 1:
ORA-06511: PL/SQL: cursor already open
ORA-06512: at "DEMO.DEMO_PKG", line 3
ORA-06512: at "DEMO.DEMO_PKG", line 7
ORA-06512: at line 4
But when the cursor declaration is brought with the declaration block of the referencing unit rather than global declaration, things change like this.
demo@ORA12C> create or replace package body demo_pkg
2 as
3 procedure p as
4 cursor c is select * from dual;
5 r c%rowtype;
6 begin
7 open c;
8 fetch c into r;
9 end;
10 end;
11 /
Package body created.
demo@ORA12C> select s.name,m.value
2 from v$statname s,
3 v$mystat m
4 where m.statistic# = s.statistic#
5 and s.name ='opened cursors current';
NAME VALUE
-------------------------------------------------- ----------
opened cursors current 7
1 row selected.
demo@ORA12C> begin
2 for i in 1..5000
3 loop
4 demo_pkg.p;
5 end loop;
6 end;
7 /
PL/SQL procedure successfully completed.
demo@ORA12C> select s.name,m.value
2 from v$statname s,
3 v$mystat m
4 where m.statistic# = s.statistic#
5 and s.name ='opened cursors current';
NAME VALUE
-------------------------------------------------- ----------
opened cursors current 7
1 row selected.
demo@ORA12C> show parameter open_cursor
NAME TYPE VALUE
--------------------------------------------- ----------- ----------------
open_cursors integer 300
demo@ORA12C>