How to pass a record to a PL/pgSQL function?

前端 未结 3 617
醉酒成梦
醉酒成梦 2021-01-04 23:43

I have 8 similar PL/pgSQL functions; they are used as INSTEAD OF INSERT/UPDATE/DELETE triggers on views to make them writable. The views each combine columns of

3条回答
  •  Happy的楠姐
    2021-01-05 00:17

    There are various options, depending on the complete picture.
    Basically, your insert function could work like this:

    CREATE FUNCTION insert_thing (_thing flavored_view)
       RETURNS int AS
    $func$
       INSERT INTO things (name) VALUES ($1.name) -- plus 30 more columns
       RETURNING id;
    $func$ LANGUAGE sql;

    Using the row type of the view, because NEW in your trigger is of this type.
    Use a simple SQL function, which can be inlined and might perform better.

    Demo call:

    SELECT insert_thing('(1, foo, 1, bar)');
    

    Inside your trigger flavored_trig ():

    inserted_id := insert_thing(NEW);
    

    Or, basically rewritten:

    IF TG_OP = 'INSERT' THEN
       INSERT INTO flavored_things(thing_id, flavor)
       VALUES (insert_thing(NEW), NEW.flavor);
       RETURN NEW;
    ELSIF ...
    

    record is not a valid type outside PL/pgSQL, it's just a generic placeholder for a yet unknown row type in PL/pgSQL) so you cannot use it for an input parameter in a function declaration.

    For a more dynamic function accepting various row types you could use a polymorphic type. Examples:

    • How to return a table by rowtype in PL/pgSQL
    • Refactor a PL/pgSQL function to return the output of various SELECT queries
    • How to write a function that returns text or integer values?

提交回复
热议问题