10
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.

Erwin Brandstetter
  • 605,456
  • 145
  • 1,078
  • 1,228
vg123
  • 235
  • 2
  • 3
  • 13

2 Answers2

26

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.

Erwin Brandstetter
  • 605,456
  • 145
  • 1,078
  • 1,228
  • :: yes.It's a simplified eample.Actually I'm using database partitioning for that table name is generating dynamically ,still IT's not working for simpler part. I used all above with dummytest in lowercase on postgres 9.1 and I'm getting following error ERROR: stack depth limit exceeded HINT: Increase the configuration parameter "max_stack_depth" (currently 2048kB), after ensuring the platform's stack depth limit is adequate. CONTEXT: SQL statement "INSERT INTO dummytest VALUES ($1,$2)" PL/pgSQL function "dummytest_insert_trigger" line 7 at EXECUTE statement – vg123 Dec 28 '12 at 09:56
  • @mona: Sounds like you may be creating an infinite loop with your triggers. It' your responsibility to avoid that. – Erwin Brandstetter Dec 28 '12 at 12:28
  • @ Erwin Brandstetter : Yes It was my mistake.Thanks your solution worked. :) :) – vg123 Dec 29 '12 at 10:12
  • This was perfect ."There is really no point in using dynamic SQL with EXECUTE as long as you have a static table name. ". – Ankur Srivastava Feb 25 '17 at 00:21
5

You need explicit cast to text:

EXECUTE format('INSERT INTO %I VALUES ($1,$2)'::text ,v_partition_name) using NEW.id,NEW.datetime;
neoneye
  • 50,398
  • 25
  • 166
  • 151
mys
  • 2,355
  • 18
  • 21