I have an INSERT
statement in Postgres 9.5+, but the INSERT sometimes doesn't actually happen because of a key conflict (I've set ON CONFLICT DO NOTHING
on the INSERT).
If the INSERT
happens, then of course the trigger runs. But if the INSERT
doesn't happen because of a key conflict, will triggers still run?
Does it depend on whether it's a BEFORE
or AFTER
trigger?
Per-row
BEFORE INSERT
triggers are fired, and possible effects on the proposed row applied, before checking for conflicts. The manual:A plain
INSERT
would raise anEXCEPTION
because of the unique violation, and that rolls back everything (except what cannot be rolled back, like incrementing a sequence).But the UPSERT with
ON CONFLICT DO NOTHING
suppresses the exception, hence the effects of any such triggers persist, even if the row proposed for insertion is skipped.(Consequently, when using
ON CONFLICT DO UPDATE ...
, effects of such triggers are reflected in the specialEXCLUDED
row that's visible in theUPDATE
part.)But
AFTER INSERT
triggers are not even fired for either case. The row is never actually inserted - with or without raising an exception.I thought of using a
RULE
instead, which can rewrite anINSERT
to run additional commands, independent of the outcome. More tricky than a trigger, but it kicks in before theINSERT
might be cancelled. However, the manual warns:So, no dice.