HiveBrain v1.2.0
Get Started
← Back to all entries
snippetsqlMajor

How to prevent a PostgreSQL trigger from being fired by another trigger?

Submitted by: @import:stackexchange-dba··
0
Viewed 0 times
postgresqlpreventtriggerfiredbeinganotherhowfrom

Problem

I have 2 triggers on one table; one works for INSERTs :

CREATE TRIGGER "get_user_name"
AFTER INSERT ON "field_data"
FOR EACH ROW EXECUTE PROCEDURE "add_info"();


This updates some values in the table.

And one for UPDATEs (to fill a history table):

CREATE TRIGGER "set_history"
BEFORE UPDATE ON "field_data"
FOR EACH ROW EXECUTE PROCEDURE "gener_history"();


The problem is that when I insert a new row in the table the procedure "add_info"() makes an update and therefore fires the second trigger, which ends with an error:

ERROR:  record "new" has no field "field1"


How can I avoid this?

Solution

(Obvious error in the trigger logic aside.)

In Postgres 9.2 or later, use the function pg_trigger_depth() that Akash already mentioned in a condition on the trigger itself (instead of the body of the trigger function), so that the trigger function is not even executed when called from another trigger (including itself - so also preventing loops).

This typically performs better and is simpler and cleaner:

CREATE TRIGGER set_history
BEFORE UPDATE ON field_data
FOR EACH ROW 
WHEN (pg_trigger_depth() 
EXECUTE FUNCTION gener_history();


In Postgres 10 or older use the keyword PROCEDURE instead of FUNCTION. See:

  • Trigger uses a procedure or a function?



The expression pg_trigger_depth() < 1 is evaluated before the trigger function is entered. So it evaluates to 0 in the first call. When called from another trigger, the value is higher and the trigger function is not executed.

Code Snippets

CREATE TRIGGER set_history
BEFORE UPDATE ON field_data
FOR EACH ROW 
WHEN (pg_trigger_depth() < 1)
EXECUTE FUNCTION gener_history();

Context

StackExchange Database Administrators Q#103402, answer score: 25

Revisions (0)

No revisions yet.