Skip to main content
1 of 10
Erwin Brandstetter
  • 182.2k
  • 28
  • 457
  • 620

There is a solution with just PL/pgSQL. Simple and elegant, too. Pretty advanced stuff, though.
Requires Postgres 9.0 or later (workaround for older versions possible).

CREATE OR REPLACE FUNCTION gesio(_tbl_in anyelement, _tbl_out regclass)
  RETURNS SETOF anyelement AS  -- (we are not returning anything)
$func$
BEGIN

FOR _tbl_in IN EXECUTE
   format('SELECT * FROM %s', pg_typeof(_tbl_in))
LOOP
    -- 1. do something with rec

    -- 2. insert the rec into events_table_out
   EXECUTE format('INSERT INTO %s SELECT ($1).*', _tbl_out)
   USING _tbl_in;
END LOOP;

END
$func$ LANGUAGE plpgsql;

Call:

SELECT gesio(NULL::t, 't1');

t and t1 being the tables with identical schema.

Using the implicit cursor of a FOR loop instead of you explicit cursor. That's generally preferable.

Major ingredients

A major obstacle to overcome was, that variables inside the function cannot be defined as polymorphic type (anyelement). This related answer on SO explains the solution. Provides a workaround for older versions, too.

Basically I am handing in a NULL value of type t, which serves three purposes:

  • Provides table name.
  • Provides table type.
  • Serves as loop variable.

Consider this related answer on SO with more details. the most interesting part being the last chapter "Various complete table types".

->SQLfiddle demo.

Aside:
If your computations for 1. do something with rec are not too sophisticated, you may be able to replace the loop with a single dynamic SQL statement, which is typically much faster.

Erwin Brandstetter
  • 182.2k
  • 28
  • 457
  • 620