Comment désactiver temporairement les déclencheurs dans PostgreSQL?

131

Je charge des données en masse et je peux recalculer toutes les modifications de déclencheur beaucoup moins cher après coup que sur une base ligne par ligne.

Comment puis-je désactiver temporairement tous les déclencheurs dans PostgreSQL?

David Schmitt
la source

Réponses:

163

Alternativement, si vous souhaitez désactiver tous les déclencheurs, pas seulement ceux de la table USER, vous pouvez utiliser:

SET session_replication_role = replica;

Cela désactive les déclencheurs pour la session en cours.

Pour réactiver pour la même session:

SET session_replication_role = DEFAULT;

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

zyzof
la source
2
Impressionnant. J'ai fait passer ma suppression en masse de 30 minutes à <1 seconde :)
Dan Lenski
7
Il est également pratique que cette commande ne désactive pas les déclencheurs de contrainte
bartolo-otrit
2
J'ai passé la dernière demi-heure à chercher en vain un moyen de contourner l'erreur "viole les contraintes de clé étrangère" dans mon environnement de test, et c'est exactement ça!
Amalgovinus
Une mise en garde: selon les documents de configuration d'exécution et les documents ALTER TABLE, cela fonctionnera avec les déclencheurs normaux mais pas ceux définis avecENABLE REPLICA ou ENABLE ALWAYS.
beldaz
Je suis sur 10.4et il semble ignorer cette déclaration ci-dessus.
Stephane
129

PostgreSQL connaît la ALTER TABLE tblname DISABLE TRIGGER USERcommande, qui semble faire ce dont j'ai besoin. Voir ALTER TABLE .

David Schmitt
la source
Et alors comment «recalculer toutes les modifications de déclenchement»?
Wojtek Kruszewski
15
Attention à la charge simultanée: ALTER TABLE ... DISABLE TRIGGER USERnécessite un verrou exclusif sur la table.
Erwin Brandstetter
3
@WojtekKruszewski, je pense que David voulait dire qu'Il pouvait recalculer manuellement les changements qui auraient été faits par déclencheur, en utilisant certaines connaissances préalables (par exemple, si le déclencheur apportera le même changement dans chaque ligne, ce qui peut être plus efficace géré par une seule UPDATE). Je ne pense pas qu'Il voulait dire que Tu peux faire ça dans toutes les situations.
Rauni Lillemets
1
La solution de @ zyzof est meilleure pour désactiver tous les déclencheurs.
uthomas
48

Pour désactiver le déclencheur

ALTER TABLE table_name DISABLE TRIGGER trigger_name

Pour activer le déclencheur

ALTER TABLE table_name ENABLE TRIGGER trigger_name
Mise
la source
1
Vous pouvez également utiliser "all" pour cela:ALTER TABLE table_name DISABLE TRIGGER all
DenisNovac
8
SET session_replication_role = replica; 

Cela ne fonctionne pas avec PostgreSQL 9.4 sur ma machine Linux si je change une table via l'éditeur de table dans pgAdmin et fonctionne si je change de table via une requête ordinaire. Les changements manuels dans la table pg_trigger ne fonctionnent pas non plus sans redémarrage du serveur mais avec une requête dynamique comme sur postgresql.nabble.com ACTIVER / DÉSACTIVER TOUS LES DÉCLENCHEMENTS DANS LA BASE DE DONNÉES fonctionnent. Cela peut être utile lorsque vous avez besoin de quelques réglages.

Par exemple, si vous avez des tables dans un espace de noms particulier, cela pourrait être:

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;

Si vous souhaitez désactiver tous les déclencheurs avec certaines fonctions de déclenchement, cela peut être:

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;

Documentation PostgreSQL pour les catalogues système


Il existe d'autres options de contrôle du processus de déclenchement de déclenchement:

ALTER TABLE ... ENABLE REPLICA TRIGGER ... - le déclencheur se déclenchera en mode réplique uniquement.

ALTER TABLE ... ENABLE ALWAYS TRIGGER ... - la gâchette se déclenchera toujours (évidemment)

Bartolo-Otrit
la source
7

Vous pouvez également désactiver les déclencheurs dans pgAdmin (III):

  1. Trouvez votre table
  2. Développez le +
  3. Trouvez votre déclencheur dans Triggers
  4. Cliquez avec le bouton droit de la souris, décochez "Trigger Enabled?"
Neil McGuigan
la source
4
SET session_replication_role = replica;  

aussi travailler pour moi dans Postgres 9.1. J'utilise les deux fonctions décrites par bartolo-otrit avec quelques modifications. J'ai modifié la première fonction pour qu'elle fonctionne pour moi car l'espace de noms ou le schéma doit être présent pour identifier correctement la table. Le nouveau code est:

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;

alors je fais simplement une requête de sélection pour chaque schéma:

SELECT disable_triggers(true,'public');
SELECT disable_triggers(true,'Adempiere');
Samih Chouhen
la source