Jak tymczasowo wyłączyć wyzwalacze w PostgreSQL?

140

Ładuję dane zbiorczo i mogę ponownie obliczyć wszystkie modyfikacje wyzwalacza znacznie taniej po fakcie niż na podstawie wiersza po wierszu.

Jak mogę tymczasowo wyłączyć wszystkie wyzwalacze w PostgreSQL?

David Schmitt
źródło

Odpowiedzi:

173

Alternatywnie, jeśli chcesz wyłączyć wszystkie wyzwalacze, a nie tylko te z tabeli USER, możesz użyć:

SET session_replication_role = replica;

Spowoduje to wyłączenie wyzwalaczy dla bieżącej sesji.

Aby ponownie włączyć dla tej samej sesji:

SET session_replication_role = DEFAULT;

Źródło: http://koo.fi/blog/2013/01/08/disable-postgresql-triggers-temporary/

zyzof
źródło
2
Niesamowite. Zrobiłem moje masowe usuwanie z 30 minut do <1 sekundy :)
Dan Lenski
8
Przydatne
2
Ostatnie pół godziny spędziłem na próżno szukając sposobu na obejście błędu „narusza ograniczenia klucza obcego” w moim środowisku testowym i to jest dokładnie to!
Amalgovinus
Jedno zastrzeżenie: zgodnie z dokumentacją konfiguracyjną środowiska uruchomieniowego i dokumentacją ALTER TABLE będzie to działać z normalnymi wyzwalaczami, ale nie z tymi ustawionymi za pomocą ENABLE REPLICAlub ENABLE ALWAYS.
beldaz
Jestem włączony 10.4i wydaje się, że ignoruję powyższe stwierdzenie.
Stephane
131

PostgreSQL zna ALTER TABLE tblname DISABLE TRIGGER USERpolecenie, które wydaje się robić to, czego potrzebuję. Zobacz ALTER TABLE .

David Schmitt
źródło
A w jaki sposób „przeliczysz wszystkie modyfikacje wyzwalacza”?
Wojtek Kruszewski
15
Ostrożnie z jednoczesnym obciążeniem: ALTER TABLE ... DISABLE TRIGGER USERwymaga wyłącznej blokady na stole.
Erwin Brandstetter
3
@WojtekKruszewski, myślę, że Dawid miał na myśli, że może przeliczyć zmiany ręcznie, które zrobiłby wyzwalacz, korzystając z wcześniejszej wiedzy (na przykład, jeśli wyzwalacz dokona tej samej zmiany w każdym wierszu, co może być wydajniejsze obsługiwane przez pojedynczą aktualizację). Nie sądzę, żeby miał na myśli, że możesz to zrobić w każdej sytuacji.
Rauni Lillemets,
1
Rozwiązanie @ zyzof jest lepsze do wyłączania wszystkich wyzwalaczy.
uthomas
51

Aby wyłączyć wyzwalacz

ALTER TABLE table_name DISABLE TRIGGER trigger_name

Włącz wyzwalacz

ALTER TABLE table_name ENABLE TRIGGER trigger_name
Mise
źródło
2
Możesz także użyć do tego „all”:ALTER TABLE table_name DISABLE TRIGGER all
DenisNovac
8
SET session_replication_role = replica; 

Nie działa z PostgreSQL 9.4 na moim komputerze z Linuksem, jeśli zmienię tabelę za pomocą edytora tabel w pgAdmin i działa, jeśli zmienię tabelę za pomocą zwykłego zapytania. Ręczne zmiany w tabeli pg_trigger również nie działają bez restartu serwera, ale działa dynamiczne zapytanie, takie jak na postgresql.nabble.com ENABLE / DISABLE ALL TRIGGERS IN DATABASE . Może to być przydatne, gdy potrzebujesz trochę strojenia.

Na przykład, jeśli masz tabele w określonej przestrzeni nazw, może to być:

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;

Jeśli chcesz wyłączyć wszystkie wyzwalacze z określoną funkcją wyzwalacza, może to być:

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;

Dokumentacja PostgreSQL dla katalogów systemowych


Istnieją inne opcje sterowania procesem wyzwalania spustu:

ALTER TABLE ... ENABLE REPLICA TRIGGER ... - wyzwalacz będzie strzelał tylko w trybie repliki.

ALTER TABELA ... WŁĄCZ ZAWSZE TRIGGER ... - spust będzie zawsze (oczywiście) odpalany

bartolo-otrit
źródło
7

Możesz także wyłączyć wyzwalacze w pgAdmin (III):

  1. Znajdź swój stolik
  2. Rozwiń +
  3. Znajdź wyzwalacz w wyzwalaczach
  4. Kliknij prawym przyciskiem myszy i usuń zaznaczenie opcji „Wyzwalanie włączone?”
Neil McGuigan
źródło
4
SET session_replication_role = replica;  

również nie pracowałem dla mnie w Postgres 9.1. używam dwóch funkcji opisanych przez Bartolo-otrita z pewnymi modyfikacjami. Zmodyfikowałem pierwszą funkcję, aby działała dla mnie, ponieważ przestrzeń nazw lub schemat muszą być obecne, aby poprawnie zidentyfikować tabelę. Nowy kod to:

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;

następnie po prostu wykonuję zapytanie wybierające dla każdego schematu:

SELECT disable_triggers(true,'public');
SELECT disable_triggers(true,'Adempiere');
Samih Chouhen
źródło