Re: most idiomatic way to iterate over an associative array?
From: Urs Metzger <urs_at_ursmetzger.de>
Date: Thu, 08 May 2008 20:02:58 +0200
Message-ID: <fvvf7m$tqn$1@online.de>
>> On May 7, 6:51 am, m..._at_pixar.com wrote:
>>
>>> This is what I'm doing now... is there a better way?
>>> It would be great if there were some construct such
>>> as 'for i in x begin ... end;'
>>> i := x.first;
>>> loop
>>> dbms_output.put_line(i);
>>> exit when i = x.last;
>>> i := x.next(i);
>>> end loop;
>>> Many TIA!
>>> Mark
>> This will break for empty collections. You can do
>>
>> SQL> set serverout on
>> SQL> DECLARE TYPE population_type IS TABLE OF NUMBER INDEX BY
>> VARCHAR2(64);
>> 2 continent_population population_type;
>> 3 which VARCHAR2(64);
>> 4 BEGIN
>> 5 dbms_output.put_line('-----------');
>> 6
>> 7 which := continent_population.FIRST;
>> 8 while which is not null loop
>> 9 dbms_output.put_line(which || ' -> ' ||
>> continent_population(which));
>> 10 which := continent_population.NEXT(which);
>> 11 end loop;
>> 12
>> 13 dbms_output.put_line('-----------');
>> 14
>> 15 continent_population('Australia') := 30000000;
>> 16 continent_population('Antarctica') := 1000; -- Creates new
>> entry
>> 17 continent_population('Antarctica') := 1001; -- Replaces
>> previous value
>> 18
>> 19 which := continent_population.FIRST;
>> 20 while which is not null loop
>> 21 dbms_output.put_line(which || ' -> ' ||
>> continent_population(which));
>> 22 which := continent_population.NEXT(which);
>> 23 end loop;
>> 24
>> 25 dbms_output.put_line('-----------');
>> 26 END;
>> 27 /
>> -----------
>> -----------
>> Antarctica -> 1001
>> Australia -> 30000000
>> -----------
>>
>> PL/SQL procedure successfully completed.
>>
>> SQL>
>>
>> Cheers
>>
>> robert
>>
>> seehttp://download.oracle.com/docs/cd/B19306_01/appdev.102/b14261/collec...http://download.oracle.com/docs/cd/B19306_01/appdev.102/b14261/collec...
Mark,
13 end;
14 /
one
two
declare
*
ERROR at line 1:
ORA-01403: no data found
ORA-06512: at line 11
16 end;
17 /
one
two
four
fifty
Date: Thu, 08 May 2008 20:02:58 +0200
Message-ID: <fvvf7m$tqn$1@online.de>
Mark D Powell schrieb:
> On May 7, 4:07 am, Robert Klemme <shortcut..._at_googlemail.com> wrote:
>> On May 7, 6:51 am, m..._at_pixar.com wrote:
>>
>>> This is what I'm doing now... is there a better way?
>>> It would be great if there were some construct such
>>> as 'for i in x begin ... end;'
>>> i := x.first;
>>> loop
>>> dbms_output.put_line(i);
>>> exit when i = x.last;
>>> i := x.next(i);
>>> end loop;
>>> Many TIA!
>>> Mark
>> This will break for empty collections. You can do
>>
>> SQL> set serverout on
>> SQL> DECLARE TYPE population_type IS TABLE OF NUMBER INDEX BY
>> VARCHAR2(64);
>> 2 continent_population population_type;
>> 3 which VARCHAR2(64);
>> 4 BEGIN
>> 5 dbms_output.put_line('-----------');
>> 6
>> 7 which := continent_population.FIRST;
>> 8 while which is not null loop
>> 9 dbms_output.put_line(which || ' -> ' ||
>> continent_population(which));
>> 10 which := continent_population.NEXT(which);
>> 11 end loop;
>> 12
>> 13 dbms_output.put_line('-----------');
>> 14
>> 15 continent_population('Australia') := 30000000;
>> 16 continent_population('Antarctica') := 1000; -- Creates new
>> entry
>> 17 continent_population('Antarctica') := 1001; -- Replaces
>> previous value
>> 18
>> 19 which := continent_population.FIRST;
>> 20 while which is not null loop
>> 21 dbms_output.put_line(which || ' -> ' ||
>> continent_population(which));
>> 22 which := continent_population.NEXT(which);
>> 23 end loop;
>> 24
>> 25 dbms_output.put_line('-----------');
>> 26 END;
>> 27 /
>> -----------
>> -----------
>> Antarctica -> 1001
>> Australia -> 30000000
>> -----------
>>
>> PL/SQL procedure successfully completed.
>>
>> SQL>
>>
>> Cheers
>>
>> robert
>>
>> seehttp://download.oracle.com/docs/cd/B19306_01/appdev.102/b14261/collec...http://download.oracle.com/docs/cd/B19306_01/appdev.102/b14261/collec...
> > I think I would consider the For I in 1..n construct > > UT1 > l > 1 declare > 2 type t_array is table of varchar2(10) index by binary_integer; > 3 t_list t_array; > 4 begin > 5 t_list(1) := 'one'; > 6 t_list(2) := 'two'; > 7 t_list(3) := 'three'; > 8 t_list(4) := 'four'; > 9 t_list(5) := 'five'; > 10 for I in 1..t_list.last loop > 11 dbms_output.put_line(t_list(I)); > 12 end loop; > 13* end; > UT1 > / > one > two > three > four > five > > PL/SQL procedure successfully completed. > > Again as Robert warned in his solution the array should not be empty. > > HTH -- Mark D Powell --
Mark,
this will work if - and only if - your array has no gaps:
SQL> declare
2 type t_array is table of varchar2(10) index by binary_integer; 3 t_list t_array; 4 begin 5 t_list(1) := 'one'; 6 t_list(2) := 'two'; 7 -- t_list(3) := 'three'; 8 t_list(4) := 'four'; 9 t_list(5) := 'five'; 10 for I in 1..t_list.last loop 11 dbms_output.put_line(t_list(I)); 12 end loop;
13 end;
14 /
one
two
declare
*
ERROR at line 1:
ORA-01403: no data found
ORA-06512: at line 11
your approach won't work for arrays with index by varchar2.
The way to do is:
SQL> declare
2 type t_array is table of varchar2(10) index by binary_integer; 3 t_list t_array; 4 i binary_integer; 5 begin 6 t_list(1) := 'one'; 7 t_list(2) := 'two'; 8 t_list(4) := 'four'; 9 t_list(50) := 'fifty'; 10 11 i := t_list.first; 12 while i is not null loop 13 dbms_output.put_line(t_list(I)); 14 i := t_list.next(i); 15 end loop;
16 end;
17 /
one
two
four
fifty
This will also work with empty collections or varchar2 indexes.
Hth,
Urs Metzger
Received on Thu May 08 2008 - 13:02:58 CDT