Here is a patch to the pod documentation of DBD::Oracle-1.16.
The patch alters the section headed 'Binding Cursors'.
The patch:
* corrects an error. When passing a cursor back from Perl to PL/SQL, bind_param_inout _must not_ be used.
* attempts to clear up a misunderstanding. It is not normally necessary to close cursors explicitly.
It also:
* introduces the Oracle 9 pre-defined type SYS_REFCURSOR.
* makes the examples compatible with 'use strict'.
I have tested my assertion that Oracle closes cursors automatically. I have not added a test to the test suite because a proper test requires access to views, including V$OPEN_CURSOR, which ordinary users cannot see.
-- Charles Jardine - Computing Service, University of Cambridge [EMAIL PROTECTED] Tel: +44 1223 334506, Fax: +44 1223 334679
diff -ur DBD-Oracle-1.16.cursor-docs/Oracle.pm DBD-Oracle-1.16/Oracle.pm --- DBD-Oracle-1.16.cursor-docs/Oracle.pm 2005-04-26 17:19:35.384862000 +0100 +++ DBD-Oracle-1.16/Oracle.pm 2004-10-21 20:07:53.000000000 +0100 @@ -2393,13 +2393,12 @@ =head1 Binding Cursors
Cursors can be returned from PL/SQL blocks. Either from stored -functions (or procedures with OUT parameters) or -from direct C<OPEN> statements, as shown below: +procedure OUT parameters or from direct C<OPEN> statements, as show below:
use DBI; use DBD::Oracle qw(:ora_types); - my $dbh = DBI->connect(...); - my $sth1 = $dbh->prepare(q{ + $dbh = DBI->connect(...); + $sth1 = $dbh->prepare(q{ BEGIN OPEN :cursor FOR SELECT table_name, tablespace_name FROM user_tables WHERE tablespace_name = :space; @@ -2410,7 +2409,7 @@ $sth1->bind_param_inout(":cursor", \$sth2, 0, { ora_type => ORA_RSET } ); $sth1->execute; # $sth2 is now a valid DBI statement handle for the cursor - while ( my @row = $sth2->fetchrow_array ) { ... } + while ( @row = $sth2->fetchrow_array ) { ... }
The only special requirement is the use of C<bind_param_inout()> with an attribute hash parameter that specifies C<ora_type> as C<ORA_RSET>. @@ -2418,46 +2417,33 @@ "ORA-06550: line X, column Y: PLS-00306: wrong number or types of arguments in call to ...".
-Here's an alternative form using a function that returns a cursor. -This example uses the pre-defined weak (or generic) REF CURSOR type -SYS_REFCURSOR. This is an Oracle 9 feature. For Oracle 8, you must -create your own REF CURSOR type in a package (see the C<curref.pl> -script mentioned at the end of this section). +Here's an alternative form using a function that returns a cursor:
# Create the function that returns a cursor - $dbh->do(q{ - CREATE OR REPLACE FUNCTION sp_ListEmp RETURN SYS_REFCURSOR - AS l_cursor SYS_REFCURSOR; + $sth1 = $dbh->prepare(q{ + CREATE OR REPLACE FUNCTION sp_ListEmp RETURN types.cursorType + AS l_cursor types.cursorType; BEGIN OPEN l_cursor FOR select ename, empno from emp order by ename; RETURN l_cursor; END; }); + # CREATE is executed in prepare().
# Use the function that returns a cursor - my $sth1 = $dbh->prepare(q{BEGIN :cursor := sp_ListEmp; END;}); + $sth1 = $dbh->prepare(q{BEGIN :cursor := sp_ListEmp; END;}); my $sth2; $sth1->bind_param_inout(":cursor", \$sth2, 0, { ora_type => ORA_RSET } ); $sth1->execute; # $sth2 is now a valid DBI statement handle for the cursor - while ( my @row = $sth2->fetchrow_array ) { ... } + while ( @row = $sth2->fetchrow_array ) { ... }
-A cursor obtained from PL/SQL as above may be passed back to PL/SQL -by binding for input, as shown in this example, which explicitly -closes a cursor: +To close the cursor you (currently) need to do this:
- my $sth3 = $dbh->prepare("BEGIN CLOSE :cursor; END;"); - $sth3->bind_param(":cursor", $sth2, { ora_type => ORA_RSET } ); + $sth3 = $dbh->prepare("BEGIN CLOSE :cursor; END;"); + $sth3->bind_param_inout(":cursor", \$sth2, 0, { ora_type => ORA_RSET } ); $sth3->execute;
-It is not normally necessary to close a cursor -explicitly in this way. Oracle will close the cursor automatically -at the first client-server interaction after the cursor statement handle is -destroyed. An explicit close may be desirable if the reference to -the cursor handle from the PL/SQL statement handle delays the destruction -of the cursor handle for too long. This reference remains until the -PL/SQL handle is re-bound, re-executed or destroyed. - See the C<curref.pl> script in the Oracle.ex directory in the DBD::Oracle source distribution for a complete working example.