Como desabilito temporariamente os gatilhos no PostgreSQL?

131

Estou carregando dados em massa e posso recalcular todas as modificações de gatilho muito mais baratas após o fato do que em uma linha por linha.

Como posso desativar temporariamente todos os gatilhos no PostgreSQL?

David Schmitt
fonte

Respostas:

163

Como alternativa, se você deseja desativar todos os gatilhos, não apenas os da tabela USER, você pode usar:

SET session_replication_role = replica;

Isso desativa os gatilhos para a sessão atual.

Para reativar a mesma sessão:

SET session_replication_role = DEFAULT;

Fonte: http://koo.fi/blog/2013/01/08/disable-postgresql-triggers-temporariamente/

zyzof
fonte
2
Impressionante. Fez a minha massa eliminação go de 30 minutos a <1 segundo :)
Dan Lenski
7
Também é útil que este comando faz gatilhos de restrição não desativar
bartolo-otrit
2
Passei a última meia hora procurando em vão uma maneira de ignorar o erro "viola as restrições de chave estrangeira" no meu ambiente de teste, e é exatamente isso!
Amalgovinus
Uma ressalva: de acordo com os documentos de configuração do tempo de execução e os documentos ALTER TABLE, isso funcionará com gatilhos normais, mas não com os definidos com ENABLE REPLICAou ENABLE ALWAYS.
beldaz
Estou ligado 10.4e parece ignorar esta afirmação acima.
Stephane
129

O PostgreSQL conhece o ALTER TABLE tblname DISABLE TRIGGER USERcomando, que parece fazer o que eu preciso. Veja ALTER TABLE .

David Schmitt
fonte
E então como você "recalcula todas as modificações de gatilho"?
Wojtek Kruszewski 20/03
15
Cuidado com a carga simultânea: ALTER TABLE ... DISABLE TRIGGER USERrequer um bloqueio exclusivo na mesa.
Erwin Brandstetter
3
@WojtekKruszewski, acho que David quis dizer que Ele pode recalcular manualmente as alterações que teriam feito por acionador, usando algum conhecimento prévio (por exemplo, se o acionador fará a mesma alteração em cada linha, o que pode ser mais eficiente) manipulados por uma única atualização). Eu não acho que Ele quis dizer que você pode fazer isso em todas as situações.
Rauni Lillemets
1
A solução do @ zyzof é melhor para desativar todos os gatilhos.
uthomas
48

Para desativar o gatilho

ALTER TABLE table_name DISABLE TRIGGER trigger_name

Para ativar gatilho

ALTER TABLE table_name ENABLE TRIGGER trigger_name
Mise
fonte
1
Você também pode usar "todos" para isso:ALTER TABLE table_name DISABLE TRIGGER all
DenisNovac
8
SET session_replication_role = replica; 

Ele não funciona com o PostgreSQL 9.4 na minha máquina Linux se eu alterar uma tabela através do editor de tabelas no pgAdmin e funciona se eu alterar a tabela através de consultas comuns. Alterações manuais na tabela pg_trigger também não funcionam sem a reinicialização do servidor, mas consultas dinâmicas como postgresql.nabble.com FUNCIONAM / DESATIVAM TODOS OS TRIGGERS NO DATABASE . Pode ser útil quando você precisar de algum ajuste.

Por exemplo, se você possui tabelas em um espaço para nome específico, pode ser:

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;

Se você deseja desativar todos os gatilhos com determinada função de gatilho, pode ser:

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;

Documentação do PostgreSQL para catálogos de sistemas


Existem outras opções de controle do processo de disparo de gatilho:

ALTER TABLE ... HABILITAR O REPLICA TRIGGER ... - o gatilho será acionado apenas no modo de réplica.

ALTER TABLE ... HABILITAR SEMPRE O TRIGGER ... - o gatilho sempre dispara (obviamente)

Bartolo-Otrit
fonte
7

Você também pode desativar os gatilhos no pgAdmin (III):

  1. Encontre sua mesa
  2. Expanda o +
  3. Encontre seu gatilho em Triggers
  4. Clique com o botão direito do mouse e desmarque "Trigger Enabled?"
Neil McGuigan
fonte
4
SET session_replication_role = replica;  

também funciona para mim no Postgres 9.1. Eu uso as duas funções descritas por Bartolo-Otrit com algumas modificações. Modifiquei a primeira função para fazê-la funcionar para mim porque o espaço para nome ou o esquema deve estar presente para identificar a tabela corretamente. O novo código é:

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;

então eu simplesmente faço uma consulta de seleção para cada esquema:

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