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

前端 未结 3 590
醉酒成梦
醉酒成梦 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条回答
  • 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?
    0 讨论(0)
  • 2021-01-05 00:23

    Basically you can convert a record to a hstore variable and pass the hstore variable instead of a record variable to a function. You convert record to hstore i.e. so:

    DECLARE r record; h hstore;
    h = hstore(r);
    

    Your helper function should also be changed so:

    CREATE FUNCTION insert_thing (new_thing hstore) RETURNS INTEGER AS $fun$
    DECLARE
        inserted_id  INT;
    BEGIN
        INSERT INTO things (name) VALUES (
            new_thing -> 'name'
            -- (plus 30 more columns)
        ) RETURNING id INTO inserted_id;
        RETURN inserted_id;
    END;
    $fun$ LANGUAGE plpgsql;
    

    And the call:

    inserted_id = insert_thing(hstore(NEW));
    

    hope it helps

    0 讨论(0)
  • 2021-01-05 00:27

    Composite types. PostgresSQL has documentation on this, you essentially need to use something like

    '()' or ROW() to construct the composite type for a row to pass into a function.

    0 讨论(0)
提交回复
热议问题