Skip to Main Content

Allow for iterating associative array key/value pairs

Lukas EderMay 3 2018 — edited Apr 27 2020

Looping over associative arrays can be a bit of a hassle in PL/SQL sometimes, especially if they're indexed by a varchar2 type.:

SET SERVEROUTPUT ON

DECLARE

  TYPE arr_t IS TABLE OF VARCHAR2(30) INDEX BY VARCHAR2(30);

  l_arr arr_t;

  l_idx VARCHAR2(30);

BEGIN

  l_arr('a') := 'x';

  l_arr('b') := 'y';

 

  l_idx := l_arr.FIRST;

  WHILE l_idx IS NOT NULL LOOP

    dbms_output.put_line(l_idx || '=' || l_arr(l_idx));

    l_idx := l_arr.NEXT(l_idx);

  END LOOP;

END;

/

The FOR loop can define implicit loop variables without explicit type references, both when looping over numbers:

FOR i IN 1 .. 10 LOOP

   dbms_output.put_line(i);

END LOOP;

Or over implicit cursors:

FOR rec IN (SELECT 1 i FROM dual) LOOP

  dbms_output.put_line(rec.i);

END LOOP;

Why not also create such an implicit FOR loop for associative arrays? E.g. using this hypothetical syntax:

SET SERVEROUTPUT ON

DECLARE

  TYPE arr_t IS TABLE OF VARCHAR2(30) INDEX BY VARCHAR2(30);

  l_arr arr_t;

BEGIN

  l_arr('a') := 'x';

  l_arr('b') := 'y';

 

  FOR key, value IN l_arr LOOP

    dbms_output.put_line(key || '=' || value);

  END LOOP;

  -- Alternative syntax akin to FORALL's syntax as suggested by Jeff Kemp: https://community.oracle.com/ideas/21601#comment-1026797

  FOR key IN INDICES OF l_arr LOOP

    dbms_output.put_line(key || '=' || l_arr(key));

  END LOOP;

END;

/

Quite a few other languages have this feature, including PHP:

foreach ($arr as $key => $value) {

  echo $key;

}

Kotlin:

for ((key, value) in map) {

  ...

}

C#:

foreach(var item in myDictionary)

{

  foo(item.Key);

  bar(item.Value);

}

Java:

for (Entry<K, V> entry : map.entrySet()) {

   System.out.println(entry.getKey());

   System.out.println(entry.getValue());

}

Newer versions of ECMAScript:

Object.entries(obj).forEach(

  ([key, value]) => console.log(key, value)

);

UPDATE: This has been implemented in Oracle 20c.

Example 6-9 Index Iterator Choice Association in Qualified Expressions

This example creates a copy of vec with values incremented by N.

result := vec_t (FOR I,j IN PAIRS OF vec INDEX I => j+n); 

This example creates a vector of the first N even numbers.

result := vec_t (FOR i IN 2.n BY 2 INDEX i/2 => i); 
Comments
Post Details
Added on May 3 2018
7 comments
5,899 views