Search code examples
postgresqlformatplpgsqlusingexecute

How to use EXECUTE FORMAT ... USING in Postgres function


CREATE OR REPLACE FUNCTION dummytest_insert_trigger()
   RETURNS trigger AS
$BODY$
DECLARE
   v_partition_name    VARCHAR(32);
BEGIN
   IF NEW.datetime IS NOT NULL THEN
      v_partition_name := 'dummyTest';            
      EXECUTE format('INSERT INTO %I VALUES ($1,$2)',v_partition_name)using NEW.id,NEW.datetime;            
   END IF;                  
   RETURN NULL;
END;
$BODY$
LANGUAGE plpgsql VOLATILE COST 100;

I'm trying to insert using:

INSERT INTO dummytest VALUES(1,'2013-01-01 00:00:00+05:30');

But it's showing error as:

ERROR: function format(unknown) does not exist
SQL state: 42883
Hint: No function matches the given name and argument types. You might need to add explicit type casts.
Context: PL/pgSQL function "dummytest_insert_trigger" line 8 at EXECUTE statement

I'm unable get the error.


Solution

  • Your function could look like this in Postgres 9.0 or later:

    CREATE OR REPLACE FUNCTION dummytest_insert_trigger()
      RETURNS trigger
      LANGUAGE plpgsql AS
    $func$
    DECLARE
       v_partition_name text := quote_ident('dummyTest');  -- assign at declaration
    BEGIN
       IF NEW.datetime IS NOT NULL THEN
          EXECUTE 'INSERT INTO ' || v_partition_name || ' VALUES ($1,$2)'
          USING NEW.id, NEW.datetime;              
       END IF;                    
    
       RETURN NULL;  -- you sure about this?
    END
    $func$;
    

    About RETURN NULL:

    I would advice against mixed case identifiers. With format(... %I ...) or quote_ident(), you get a table named "dummyTest", which you'll have to double quote for the rest of its existence. Related:

    Use lower case instead:

    quote_ident('dummytest')
    

    There is really no point in using dynamic SQL with EXECUTE as long as you have a static table name. But that's probably just the simplified example?

    Aside: this kind of trigger is obsolete with declarative partitioning in Postgres 10 or later.