John Lucabech
John Lucabech

Reputation: 156

INSERT from trigger not happening?

I'm new to triggers in PostgreSQL.
I have 3 tables in this example table1, table2 and table3.

The problem is the INSERT on table3 is not happening. The INSERT on test table is fine and the logged insert query can be executed without troubles, so I don't know why it's not executed inside the trigger/function.

CREATE OR REPLACE FUNCTION my_trigger() RETURNS TRIGGER AS $my_trigger$
DECLARE r RECORD;
BEGIN
  FOR r IN SELECT t2.id_t2, t2.name_1, t2.name_2, t2.name_3 FROM table2 t2 WHERE t2.product_id=NEW.product_id 
  LOOP
    EXECUTE 'INSERT INTO table3 (id_t3, id_t1, name_1, name_2, name_3, bool_t2) VALUES (' || r.id_t2 || ',' || NEW.id_t1 || ', ''' || r.name_1 || ''',''' || r.name_2 || ''',''' || r.name_3 || ''', TRUE);';
    INSERT INTO test (field1, field2) VALUES(r.id_t2, 'INSERT INTO table3 (id_t3, id_t1, name_1, name_2, name_3, bool_t2) VALUES (' || r.id_t2 || ',' || NEW.id_t1 || ', ''' || r.name_1 || ''',''' || r.name_2 || ''',''' || r.name_3 || ''', TRUE);');
  END LOOP;
RETURN NEW;
END;
$my_trigger$ LANGUAGE plpgsql;

Edit: As @Rachcha asked, the trigger itself is defined this way:

CREATE TRIGGER my_trigger
  AFTER INSERT
  ON table1
  FOR EACH ROW
  EXECUTE PROCEDURE my_trigger();

Edit 2: I've also tried to insert without EXECUTE, but the result is the same: no errors but no fields inserted into table3.

Upvotes: 2

Views: 3524

Answers (1)

Erwin Brandstetter
Erwin Brandstetter

Reputation: 656714

Simpler function

It makes no sense to RETURN NEW in an AFTER trigger. Use RETURN NULL instead. The manual:

The return value is ignored for row-level triggers fired after an operation, and so they can return NULL.

No point in using a LOOP. Use a simple SQL statement instead.
No point in using dynamic SQL with EXECUTE.
This should work:

CREATE OR REPLACE FUNCTION my_trigger()
  RETURNS trigger
  LANGUAGE plpgsql AS
$func$
BEGIN
   INSERT INTO table3
         (   id_t3,     id_t1,    name_1, bool_t2)
   SELECT t2.id_t2, NEW.id_t1, t2.name_1, true
   FROM   table2 t2
   WHERE  t2.product_id = NEW.product_id;

   INSERT INTO test
         (  field1, field2)
   SELECT t2.id_t2, 'INSERT ...'
   FROM   table2 t2
   WHERE  t2.product_id = NEW.product_id;

   RETURN NULL;
END
$func$;

Or SELECT from table2 once in a CTE and use that in multiple INSERT commands:

...
   WITH t2 AS (
      SELECT t.id_t2, t.name_1
      FROM   table2 t
      WHERE  t.product_id = NEW.product_id
      )
   , ins_t3 AS (
      INSERT INTO table3
            (   id_t3,     id_t1,    name_1, bool_t2)
      SELECT t2.id_t2, NEW.id_t1, t2.name_1, true
      FROM   t2
      )
   INSERT INTO test
         (  field1, field2)
   SELECT t2.id_t2, 'INSERT ...'
   FROM   t2;
...

fiddle
Old sqlfiddle

Debugging

If it doesn't work, the problem is something that is not in your question. Do you have any other triggers or rules defined on table1 or table test?

To debug, add this line to your trigger function to see if you even get there and what values are in NEW

RAISE EXCEPTION 'Values in NEW: %', NEW::text;

Upvotes: 1

Related Questions