In 8i, you would have to fill a collection up (a local variable) and return the entire collection at the end (eg: client gets first row AFTER you process last row and all rows must fit into PGA memory)
by "instead of calling.... opens the cursor themsevles"
I mean, instead of the client preparing and executing:
begin demo_pkg.b( :x ); end;
client prepares and executes
select * from table( demo_pkg.b );
the client is whatever was getting the refcursor originally.
types are unchanged, here are the mods for 8i:
tkyte@ORA8IW> create or replace package demo_pkg
2 as
3 type rc is ref cursor;
4 procedure a ( p_input in number, p_cursor in out rc );
5 function b return myArrayType ;
6 end;
7 /
Package created.
tkyte@ORA8IW> create or replace package body demo_pkg
2 as
3 procedure a ( p_input in number, p_cursor in out rc )
4 is
5 begin
6 open p_cursor for
7 select user_id, created, username
8 from all_users
9 where user_id = p_input;
10 end;
11
12 function b return myArrayType
13 is
14 l_cursor rc;
15 l_data myScalarType := myScalarType( null, null, null );
16 l_array myArrayType := myArrayType();
17 begin
18 for x in ( select * from all_users where rownum < 8 )
19 loop
20 a( x.user_id, l_cursor );
21 loop
22 fetch l_cursor into l_data.x, l_data.y, l_data.z;
23 exit when l_cursor%notfound;
24 l_array.extend;
25 l_array(l_array.count) := l_data;
26 end loop;
27 close l_cursor;
28 end loop;
29 return l_array;
30 end;
31 end;
32 /
Package body created.
tkyte@ORA8IW>
tkyte@ORA8IW> select * from table( cast( demo_pkg.b as myArrayType ) );
X Y Z
---------- --------- ------------------------------
0 14-NOV-00 SYS
5 14-NOV-00 SYSTEM
11 14-NOV-00 OUTLN
41 08-NOV-04 OPS$TKYTE
25 14-NOV-00 AURORA$JIS$UTILITY$
26 14-NOV-00 OSE$HTTP$ADMIN
27 14-NOV-00 AURORA$ORB$UNAUTHENTICATED
7 rows selected.