Yes, owa_util.vc_arr can (but I would just use my own type).
Here is a very small example using scott/tiger and the DEPT table.
You will call show_data from the URL like this:
</code>
http://yourhost/DCDname/owa/demo_pkg.show_data?p_rows=3 <code>
And that would let you see 3 rows at a time. The do_something routine gets ARRAYS of data, one element for each line on the previous page. It processes these one by one (note the use of the OLD values to prevent lost updates and the use of htf.escape_sc to avoid issues with strings that have &, ", <, > and so on in them)...
create or replace package demo_pkg
as
type myArray is table of varchar2(4000)
index by binary_integer;
procedure show_data( p_rows in number default 2 );
procedure do_something( p_old_deptno in myArray,
p_new_deptno in myArray,
p_old_dname in myArray,
p_new_dname in myArray,
p_rows in number default 2);
end;
/
create or replace package body demo_pkg
as
procedure show_data( p_rows in number default 2 )
is
begin
htp.formOpen( 'demo_pkg.do_something' );
htp.formHidden( 'p_rows', p_rows );
htp.tableOpen;
for x in ( select htf.escape_sc(deptno) deptno,
htf.escape_sc(dname) dname
from dept
where rownum <= p_rows )
loop
htp.p( '<tr><td>' );
htp.formHidden( 'p_old_deptno', x.deptno);
htp.formText( 'p_new_deptno', cvalue => x.deptno );
htp.p( '</td><td>' );
htp.formHidden( 'p_old_dname', x.dname);
htp.formText( 'p_new_dname', cvalue => x.dname );
htp.p( '</td></tr>' );
end loop;
htp.tableClose;
htp.formSubmit;
htp.formClose;
end;
procedure do_something( p_old_deptno in myArray,
p_new_deptno in myArray,
p_old_dname in myArray,
p_new_dname in myArray,
p_rows in number default 2 )
is
begin
for i in 1 .. p_old_deptno.count
loop
update dept
set deptno = p_new_deptno(i),
dname = p_new_dname(i)
where deptno = p_old_deptno(i)
and dname = p_old_dname(i);
htp.bold( 'update to dept ' || p_old_deptno(i));
if ( sql%rowcount = 0 )
then
htp.bold( ' failed, someone else changed it' );
else
htp.bold( ' succeeded...' );
end if;
htp.br;
end loop;
show_data(p_rows);
end;
end;
/