I know that PostgreSQL can create a trigger that catches more than one event (such as UPDATE
and INSERT
) as shown below:
CREATE TRIGGER my_trigger1
AFTER UPDATE OR INSERT
ON my_table1
FOR EACH ROW
EXECUTE FUNCTION my_function1();
and determine event by TG_OP
:
BEGIN
IF TG_OP = 'UPDATE' THEN
-- do something when event is update
ELSIF TG_OP = 'INSERT' THEN
-- do something when event is insert
END IF;
RETURN NULL; -- result is ignored since this is an AFTER trigger
END$$;
My question is, is it possible to create a trigger that can catch multiple events (BEFORE
, AFTER
), as shown below?
CREATE TRIGGER my_trigger2()
BEFORE INSERT OR AFTER INSERT
ON my_table2
FOR EACH ROW
EXECUTE FUNCTION my_function2();
and catch event by TG_WHEN
:
BEGIN
IF TG_WHEN = 'AFTER' THEN
-- do something when event is AFTER
RETURN NULL; -- because AFTER
ELSIF TG_WHEN = 'BEFORE' THEN
NEW.some_column = 'some_value';
RETURN NEW;
END IF;
END$$;
If it’s not possible, then what is the use of the TG_WHEN keyword?.
PostgreSQL version: 15.1;
2
Answers
As commented by @RichardHuxton and @Bergi, it is not possible to create triggers for both
UPDATE
andINSERT
events in a single statement or query, as illustrated in the example provided in the question. Instead, we can create two separate triggers forUPDATE
andINSERT
events that execute the same function. Then, we can useTG_WHEN
to perform the desired actions.AFTER
and one forBEFORE
, that execute the same functionAs some have stated in comments answering your question if you want a trigger to execute BEFORE and AFTER you have to declare two triggers that execute the same function.
Use of
OR
The keyword
OR
is used to specify multiple events as per the docs:So it is not correct to declare
BEFORE INSERT OR AFTER UPDATE
which also wouldn’t make any sense to the machine because it is a completely arbitrary command. What you are looking for would be of the formBEFORE INSERT AND AFTER UPDATE
but this doesn’t exist.Use of
TG_WHEN
The
TG_WHEN
is used to group various operations under the same function, but nonetheless you still have to create as many triggers as operations you want to catch (INSERT
,DELETE
orUPDATE
). This example, taken from the docs, illustrates the use ofTG_WHEN
:From a clean code and good practice standpoint I would suggest the following:
after_insert_trigger
,before_update_trigger
and so on…