212

I'm bulk loading data and can re-calculate all trigger modifications much more cheaply after the fact than on a row-by-row basis.

How can I temporarily disable all triggers in PostgreSQL?

David Schmitt
  • 58,259
  • 26
  • 121
  • 165

7 Answers7

253

Alternatively, if you are wanting to disable all triggers, not just those on the USER table, you can use:

SET session_replication_role = replica;

This disables triggers for the current session.

To re-enable for the same session:

SET session_replication_role = DEFAULT;

Source: http://koo.fi/blog/2013/01/08/disable-postgresql-triggers-temporarily/

zyzof
  • 3,415
  • 1
  • 25
  • 21
163

PostgreSQL knows the ALTER TABLE tblname DISABLE TRIGGER USER command, which seems to do what I need. See ALTER TABLE.

David Schmitt
  • 58,259
  • 26
  • 121
  • 165
  • And then how do you "re-calculate all trigger modifications"? – Wojtek Kruszewski Mar 20 '14 at 11:11
  • 26
    Careful with concurrent load: `ALTER TABLE ... DISABLE TRIGGER USER` requires an exclusive lock on the table. – Erwin Brandstetter May 27 '14 at 22:14
  • 4
    @WojtekKruszewski, I think that David meant that He can re-calculate the changes manually that would have done by trigger, by using some prior knowledge (for example, if the trigger will make the same change in every row, which can be more efficiently handled by a single UPDATE). I don't think that He meant that You can do this in every situation. – Rauni Lillemets Aug 05 '14 at 10:29
  • 1
    @zyzof's solution is better for disabling all triggers. – uthomas Mar 01 '17 at 07:17
  • 1
    But this has the BIG problem that you have to use the database exclusively, because the triggers will also be disabled in other sessions! – Daniel Jun 22 '23 at 06:18
  • @Daniel Really? Should be fine if you disable and re-enable them in a transaction – Bergi Aug 30 '23 at 01:23
103

For disable trigger

ALTER TABLE table_name DISABLE TRIGGER trigger_name

For enable trigger

ALTER TABLE table_name ENABLE TRIGGER trigger_name
Mise
  • 3,267
  • 1
  • 22
  • 22
10
SET session_replication_role = replica; 

It doesn't work with PostgreSQL 9.4 on my Linux machine if i change a table through table editor in pgAdmin and works if i change table through ordinary query. Manual changes in pg_trigger table also don't work without server restart but dynamic query like on postgresql.nabble.com ENABLE / DISABLE ALL TRIGGERS IN DATABASE works. It could be useful when you need some tuning.

For example if you have tables in a particular namespace it could be:

create or replace function disable_triggers(a boolean, nsp character varying) returns void as
$$
declare 
act character varying;
r record;
begin
    if(a is true) then
        act = 'disable';
    else
        act = 'enable';
    end if;

    for r in select c.relname from pg_namespace n
        join pg_class c on c.relnamespace = n.oid and c.relhastriggers = true
        where n.nspname = nsp
    loop
        execute format('alter table %I %s trigger all', r.relname, act); 
    end loop;
end;
$$
language plpgsql;

If you want to disable all triggers with certain trigger function it could be:

create or replace function disable_trigger_func(a boolean, f character varying) returns void as
$$
declare 
act character varying;
r record;
begin
    if(a is true) then
        act = 'disable';
    else
        act = 'enable';
    end if;

    for r in select c.relname from pg_proc p 
        join pg_trigger t on t.tgfoid = p.oid
        join pg_class c on c.oid = t.tgrelid
        where p.proname = f
    loop
        execute format('alter table %I %s trigger all', r.relname, act); 
    end loop;
end;
$$
language plpgsql;

PostgreSQL documentation for system catalogs


There are another control options of trigger firing process:

ALTER TABLE ... ENABLE REPLICA TRIGGER ... - trigger will fire in replica mode only.

ALTER TABLE ... ENABLE ALWAYS TRIGGER ... - trigger will fire always (obviously)

bartolo-otrit
  • 2,396
  • 3
  • 32
  • 50
8

You can also disable triggers in pgAdmin (III):

  1. Find your table
  2. Expand the +
  3. Find your trigger in Triggers
  4. Right-click, uncheck "Trigger Enabled?"
Neil McGuigan
  • 46,580
  • 12
  • 123
  • 152
8
SET session_replication_role = replica;  

also dosent work for me in Postgres 9.1. i use the two function described by bartolo-otrit with some modification. I modified the first function to make it work for me because the namespace or the schema must be present to identify the table correctly. The new code is :

CREATE OR REPLACE FUNCTION disable_triggers(a boolean, nsp character varying)
  RETURNS void AS
$BODY$
declare 
act character varying;
r record;
begin
    if(a is true) then
        act = 'disable';
    else
        act = 'enable';
    end if;

    for r in select c.relname from pg_namespace n
        join pg_class c on c.relnamespace = n.oid and c.relhastriggers = true
        where n.nspname = nsp
    loop
        execute format('alter table %I.%I %s trigger all', nsp,r.relname, act); 
    end loop;
end;
$BODY$
  LANGUAGE plpgsql VOLATILE
  COST 100;
ALTER FUNCTION disable_triggers(boolean, character varying)
  OWNER TO postgres;

then i simply do a select query for every schema :

SELECT disable_triggers(true,'public');
SELECT disable_triggers(true,'Adempiere');
Samih Chouhen
  • 81
  • 1
  • 1
5

A really elegant way to handle this is to create a role that handles database population and set replication for that role:

ALTER ROLE role_name SET session_replication_role = 'replica';

That way you can use that role for populating data and not have to worry about disabling and renabling triggers etc.

public static void
  • 1,153
  • 11
  • 20