HiveBrain v1.2.0
Get Started
← Back to all entries
snippetsqlModerate

How can I return multiple rows of records in PL/pgSQL

Submitted by: @import:stackexchange-dba··
0
Viewed 0 times
rowscanreturnrecordsmultiplehowpgsql

Problem

I am trying to return multiple records using RECORD data type, is there a way I can append to RECORD and add/append a new value with each iteration to this RECORD.

that is, I want to append to rec so that rec becomes a set of rows when the loop is over, which I can just RETURN at the end of my function.
Currently, I am doing this -

SELECT temp_table.col1, temp_table.col2, temp_table.col3
      INTO rec
      FROM temp_table
      WHERE temp_table.col3 = false;


my full code is here:

CREATE OR REPLACE FUNCTION validation()
  RETURNS RECORD AS $
DECLARE
        rec RECORD;
        temp_row RECORD;
BEGIN

  CREATE TEMPORARY TABLE temp_table (col1 TEXT, col2 INTEGER, col3 BOOLEAN) ON COMMIT DROP;

  FOR temp_row IN SELECT * FROM staging.validation
  LOOP

    RAISE NOTICE 'sql: %', temp_row.sql;

    EXECUTE format('INSERT INTO temp_table %s', temp_row.sql);

    IF (SELECT DISTINCT temp_table.col3 FROM temp_table WHERE temp_table.col3 = false)=false THEN
      RAISE NOTICE 'there is a false value';

      SELECT temp_table.col1, temp_table.col2, temp_table.col3
      INTO rec
      FROM temp_table
      WHERE temp_table.col3 = false;
    END IF;

  END LOOP;
  RETURN rec;
END; $
LANGUAGE plpgsql;


Current output after SELECT validation();

validation
(crea_ddf,8095,f)


Desired Output

validation
(crea_ddf,8095,f)
(some_source_system,some_count,f)
(some_other_source_system,some_count,f)
(.....)

Solution

The function needs to return a SETOF RECORD instead of RECORD and have one RETURN NEXT per row instead of a single RETURN, as in:

CREATE FUNCTION test() RETURNS SETOF RECORD AS $
DECLARE
 rec record;
BEGIN
  select 1,2 into rec;
  return next rec;

  select 3,4 into rec;
  return next rec;
END $ language plpgsql;


Caller:

=> select * from test() as x(a int ,b int) ;
a | b
---+---
1 | 2
3 | 4
(2 rows)

Note that SQL being strongly and statically typed, the RECORD pseudo-type is hard to work with.

Often it's less cumbersome to use right from the start a composite type with a full definition of names and type for each column, either with the TABLE(...) syntax for an anonymous type or with CREATE TYPE for a persistent named type.

Code Snippets

CREATE FUNCTION test() RETURNS SETOF RECORD AS $$
DECLARE
 rec record;
BEGIN
  select 1,2 into rec;
  return next rec;

  select 3,4 into rec;
  return next rec;
END $$ language plpgsql;

Context

StackExchange Database Administrators Q#186257, answer score: 19

Revisions (0)

No revisions yet.