68

In plpgsql, I want to get the array contents one by one from a two dimension array.

DECLARE
  m varchar[];
  arr varchar[][] := array[['key1','val1'],['key2','val2']];
BEGIN
  for m in select arr
  LOOP
    raise NOTICE '%',m;
  END LOOP;
END;

But the above code returns:

{{key1,val1},{key2,val2}}

in one line. I want to be able to loop over and call another function which takes parameters like:

another_func(key1,val1)
Erwin Brandstetter
  • 605,456
  • 145
  • 1,078
  • 1,228
blue01
  • 2,035
  • 2
  • 23
  • 38

1 Answers1

144

Since PostgreSQL 9.1

There is the convenient FOREACH which can loop over slices of arrays. The manual:

The target variable must be an array, and it receives successive slices of the array value, where each slice is of the number of dimensions specified by SLICE.

DO
$do$
DECLARE
   m   text[];
   arr text[] := '{{key1,val1},{key2,val2}}';  -- array literal
BEGIN
   FOREACH m SLICE 1 IN ARRAY arr
   LOOP
      RAISE NOTICE 'another_func(%,%)', m[1], m[2];
   END LOOP;
END
$do$;

db<>fiddle here - with a function printing results, instead of DO

LANGUAGE plpgsql is the default for a DO statement so we can omit the declaration.

There is no difference between text[] and text[][] for the Postgres type system. See:

Postgres 9.0 or older

DO
$do$
DECLARE
   arr text[] := array[['key1','val1'],['key2','val2']];  -- array constructor
BEGIN
   FOR i IN array_lower(arr, 1) .. array_upper(arr, 1)
   LOOP
      RAISE NOTICE 'another_func(%,%)', arr[i][1], arr[i][2];
   END LOOP;
END
$do$;
Erwin Brandstetter
  • 605,456
  • 145
  • 1,078
  • 1,228