Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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;
ALTER FUNCTION dummytest_insert_trigger()
  OWNER TO postgres;

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.

like image 472
vg123 Avatar asked Dec 28 '12 06:12

vg123


People also ask

What is execute format?

The execute format produces code that executes the function. The execute format is identical with the standard format, except that you add the MF=(E,address)

How PostgreSQL query execute?

To do this in PL/pgSQL, use the PERFORM statement: PERFORM query ; This executes query and discards the result. Write the query the same way you would write an SQL SELECT command, but replace the initial keyword SELECT with PERFORM .

What is $$ in PostgreSQL function?

It can be used to replace single quotes enclosing string literals (constants) anywhere in SQL scripts. The body of a function happens to be such a string literal. Dollar-quoting is a PostgreSQL-specific substitute for single quotes to avoid escaping of nested single quotes (recursively).


2 Answers

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

CREATE OR REPLACE FUNCTION dummytest_insert_trigger()
  RETURNS trigger 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$  LANGUAGE plpgsql;

About RETURN NULL:

  • To ignore result in BEFORE TRIGGER of PostgreSQL?

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

  • Are PostgreSQL column names case-sensitive?

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?

like image 126
Erwin Brandstetter Avatar answered Oct 04 '22 18:10

Erwin Brandstetter


You need explicit cast to text:

EXECUTE format('INSERT INTO %I VALUES ($1,$2)'::text ,v_partition_name) using NEW.id,NEW.datetime;
like image 34
mys Avatar answered Oct 04 '22 17:10

mys