Search code examples
databasepostgresqlfor-loopmultidimensional-arrayplpgsql

Loop over array dimension in plpgsql


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)

Solution

  • 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$;