How to write a FOR EACH loop in PL/SQL?
Asked Answered
E

3

8

Is it possible to run a for each loop on a PL/SQL array?

Eversion answered 22/3, 2012 at 16:54 Comment(4)
Avoid looping constructs in SQL. Start thinking in SET based operations. simple-talk.com/sql/database-administration/…Greenstein
The Oracle documentation is comprehensive, online and free. You shoudl learn how to use it to answer trivial syntax questions for yourself. Here is the section on PL/SQL loops. docs.oracle.com/cd/B28359_01/appdev.111/b28370/…Ocasio
Reading the documentaion would also have answered your subsequent question https://mcmap.net/q/1324687/-can-39-t-seem-to-find-a-way-to-loop-through-a-pl-sql-array/146325 tooOcasio
@Ocasio Useless rtfm link. A for-each loop iterates over a list of values. The Oracle documentation describes only a basic for loop iterating over numbers.Oralee
H
14
for i in my_array.first ..my_array.last loop
  --do_something with my_array(i);
end loop;
Heel answered 22/3, 2012 at 16:59 Comment(1)
As some comments in ceving's link stated, this would return an error if my_array is empty. For that case, it is better to use FOR i IN 1 .. my_array.COUNTDown
A
2

It's no possible to iterate over the associative arrays with a non numeric index with a FOR-loop. The solution below works just fine.

-- for-each key in (associative-array) loop ... 
declare
    type items_type is table of varchar2(32) index by varchar2(32);
    items items_type;
begin
    items('10') := 'item 10';
    items('20') := 'item 20';
    items('30') := 'item 30';
    dbms_output.put_line('items=' || items.count); 

    <<for_each>> declare key varchar2(32); begin loop 
        key := case when key is null then items.first else items.next(key) end; 
        exit when key is null;
        dbms_output.put_line('item(' || key || ')=' || items(key));
        --do something with an item
    end loop; end for_each;
end;
Acupuncture answered 29/7, 2016 at 15:43 Comment(0)
C
0

In my opinion 0xdb solution is best. Even if you have numeric index it is better to us this construct

DECLARE
  TYPE TTab_SomeTable IS TABLE OF VARCHAR2(2000) INDEX BY PLS_INTEGER;
  --
  vt_SomeTable TTab_SomeTable;
  vi_Idx       NUMBER;
BEGIN
  vt_SomeTable(1) := 'First';
  vt_SomeTable(2) := 'Second';
  vt_SomeTable(5) := 'Fifth';
  vt_SomeTable(10) := 'Tenth';

  
  vi_Idx := vt_SomeTable.FIRST;
  LOOP
    --
    EXIT WHEN vi_Idx IS NULL;
    --
    dbms_output.Put_Line('vt_SomeTable(' || vi_Idx || ') = ' || vt_SomeTable(vi_Idx));
    --
    vi_Idx := vt_SomeTable.NEXT(vi_Idx);
    --
  END LOOP vi_Idx;
END;

It is not susceptible to index discontinuity like below two examples, which will fail on index 3:

DECLARE
  TYPE TTab_SomeTable IS TABLE OF VARCHAR2(2000) INDEX BY PLS_INTEGER;
  --
  vt_SomeTable TTab_SomeTable;
BEGIN
  vt_SomeTable(1) := 'First';
  vt_SomeTable(2) := 'Second';
  vt_SomeTable(5) := 'Fifth';
  vt_SomeTable(10) := 'Tenth';

  -- Throw No_data_found on vi_Idx = 3
  FOR vi_Idx IN vt_SomeTable.FIRST .. vt_SomeTable.LAST
  LOOP
    dbms_output.Put_Line('vt_SomeTable(' || vi_Idx || ') = ' || vt_SomeTable(vi_Idx));
  END LOOP vi_Idx;
END;



DECLARE
  TYPE TTab_SomeTable IS TABLE OF VARCHAR2(2000) INDEX BY PLS_INTEGER;
  --
  vt_SomeTable TTab_SomeTable;
BEGIN
  vt_SomeTable(1) := 'First';
  vt_SomeTable(2) := 'Second';
  vt_SomeTable(5) := 'Fifth';
  vt_SomeTable(10) := 'Tenth';

  -- Throw No_data_found on vi_Idx = 3.
  FOR vi_Idx IN 1 .. vt_SomeTable.COUNT
  LOOP
    dbms_output.Put_Line('vt_SomeTable(' || vi_Idx || ') = ' || vt_SomeTable(vi_Idx));
  END LOOP vi_Idx;
END;
Co answered 7/7, 2022 at 10:42 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.