Reputation: 2991
I'm trying to do something very basic in PL/SQL, but I keep getting owned... how do I push items into an array and iterate through them?
Googling it seems to suggest using owa_text.multi_line
;
owa_text.multi_line
is a record of this type:
/* A multi_line is just an abstract datatype which can hold */
/* large amounts of text data as one piece. */
type multi_line is record
(
rows vc_arr,
num_rows integer,
partial_row boolean
);
To iterate through vc_arr
, we have to use l_array.first.. l_array.last
. But that gives an error while trying to access it.
Here's a simple sample to find load distinct values into an array:
declare
l_persons owa_text.multi_line := owa_text.new_multi();
/* Documentation of owa_text.new_multi(): Standard "make element" routines. */
--function new_multi return multi_line;
l_value_exists boolean := false;
cursor c_get_orders is
select person,
choice
from my_orders;
begin
for i in c_get_orders loop
l_value_exists := false;
for j in l_persons.rows.first.. l_persons.rows.last loop --Fails here,
--PL/SQL: numeric or value error
if l_persons.rows(j) = i.person then
l_value_exists := true;
exit;
end if;
end loop;
if not l_value_exists then
owa_text.add2multi(i.person, l_persons);
end if;
end loop;
for i in l_persons.rows.first.. l_persons.rows.last loop
write_to_log(l_persons.rows(i));
end loop;
end;
What am I missing? How do I do this?
EDIT: Here's a script to get set up, if it helps follow the example:
create table my_orders
(
person varchar2(4000 byte),
choice varchar2(4000 byte)
);
insert into my_orders
(person, choice)
values
('Tom', 'Juice');
insert into my_orders
(person, choice)
values
('Jane', 'Apple');
insert into my_orders
(person, choice)
values
('Tom', 'Cake');
insert into my_orders
(person, choice)
values
('Jane', 'Chocolate');
insert into my_orders
(person, choice)
values
('Tom', 'Coffee');
commit;
Upvotes: 1
Views: 6347
Reputation: 30775
Presumable, the new_multi()
method initializes an empty collection.
One of the more esoteric features of Oracle collections is that using FIRST
/ LAST
to iterate over empty collections doesn't work - you have to either check whether the collection is empty, or use 1 .. <collection>.COUNT
instead:
declare
type t_number_nt is table of number;
l_numbers t_number_nt := t_number_nt();
begin
-- raises ORA-006502
/* for i in l_numbers.first .. l_numbers.last
loop
dbms_output.put_line(l_numbers(i));
end loop;
*/
-- doesn't raise an error
for i in 1 .. l_numbers.count loop
dbms_output.put_line(l_numbers(i));
end loop;
end;
UPDATE
For a more thorough explanation of techniques for iterating over PL/SQL collections, see this OTN article by Steven Feuerstein
Upvotes: 2
Reputation: 6476
It has to be like this:
declare
l_persons owa_text.multi_line;
begin
OWA_TEXT.new_multi (l_persons);
FOR i IN 1 .. l_persons.num_rows
loop
null;
end loop;
end;
Upvotes: 1