Bagaimana cara menonaktifkan pemicu sementara di PostgreSQL?

131

Saya memuat data massal dan dapat menghitung ulang semua modifikasi pemicu jauh lebih murah setelah fakta daripada secara baris-demi-baris.

Bagaimana saya bisa menonaktifkan sementara semua pemicu di PostgreSQL?

David Schmitt
sumber

Jawaban:

163

Atau, jika Anda ingin menonaktifkan semua pemicu, bukan hanya yang ada di tabel USER, Anda dapat menggunakan:

SET session_replication_role = replica;

Ini menonaktifkan pemicu untuk sesi saat ini.

Untuk mengaktifkan kembali untuk sesi yang sama:

SET session_replication_role = DEFAULT;

Sumber: http://koo.fi/blog/2013/01/08/disable-postgresql-triggers-temporently/

zyzof
sumber
2
Luar biasa. Membuat penghapusan massal saya berjalan dari 30 menit menjadi <1 detik :)
Dan Lenski
7
Berguna juga bahwa perintah ini tidak menonaktifkan pemicu kendala
bartolo-otrit
2
Saya telah menghabiskan setengah jam terakhir dengan sia-sia mencari cara untuk memotong kesalahan "melanggar batasan kunci asing" di lingkungan pengujian saya, dan inilah tepatnya!
Amalgovinus
Satu peringatan: menurut runtime config docs dan ALTER TABLE docs ini akan berfungsi dengan pemicu normal tetapi tidak yang diatur dengan ENABLE REPLICAatau ENABLE ALWAYS.
beldaz
Saya aktif 10.4dan sepertinya mengabaikan pernyataan di atas.
Stephane
129

PostgreSQL tahu ALTER TABLE tblname DISABLE TRIGGER USERperintahnya, yang sepertinya melakukan apa yang saya butuhkan. Lihat ALTER TABEL .

David Schmitt
sumber
Lalu bagaimana Anda "menghitung ulang semua modifikasi pemicu"?
Wojtek Kruszewski
15
Hati-hati dengan beban bersamaan: ALTER TABLE ... DISABLE TRIGGER USERmembutuhkan kunci eksklusif di atas meja.
Erwin Brandstetter
3
@WojtekKruszewski, saya pikir David berarti bahwa dia dapat menghitung ulang perubahan secara manual yang akan dilakukan oleh pemicu, dengan menggunakan beberapa pengetahuan sebelumnya (misalnya, jika pemicu akan membuat perubahan yang sama di setiap baris, yang bisa lebih efisien ditangani oleh satu UPDATE tunggal). Saya tidak berpikir bahwa Ia bermaksud agar Anda dapat melakukan ini dalam setiap situasi.
Rauni Lillemets
1
Solusi @ zyzof lebih baik untuk menonaktifkan semua pemicu.
uthomas
48

Untuk menonaktifkan pemicu

ALTER TABLE table_name DISABLE TRIGGER trigger_name

Untuk mengaktifkan pemicu

ALTER TABLE table_name ENABLE TRIGGER trigger_name
Mise
sumber
1
Anda juga dapat menggunakan "semua" untuk ini:ALTER TABLE table_name DISABLE TRIGGER all
DenisNovac
8
SET session_replication_role = replica; 

Itu tidak bekerja dengan PostgreSQL 9.4 di mesin Linux saya jika saya mengubah tabel melalui editor tabel di pgAdmin dan berfungsi jika saya mengubah tabel melalui permintaan biasa. Perubahan manual dalam tabel pg_trigger juga tidak berfungsi tanpa server restart tetapi permintaan dinamis seperti pada postgresql.nabble.com AKTIFKAN / Nonaktifkan SEMUA PEMICU DALAM DATABASE . Ini bisa berguna ketika Anda membutuhkan penyetelan.

Sebagai contoh jika Anda memiliki tabel di namespace tertentu itu bisa:

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;

Jika Anda ingin menonaktifkan semua pemicu dengan fungsi pemicu tertentu, bisa jadi itu:

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;

Dokumentasi PostgreSQL untuk katalog sistem


Ada opsi kontrol lain proses pemicu pemicu:

ALTER TABLE ... ENABLE REPLICA TRIGGER ... - pelatuk akan menyala dalam mode replika saja.

ALTER TABEL ... AKTIFKAN SELALU PEMICU ... - pelatuk akan selalu menyala (jelas)

Bartolo-Otrit
sumber
7

Anda juga dapat menonaktifkan pemicu di pgAdmin (III):

  1. Temukan meja Anda
  2. Perluas +
  3. Temukan pemicu Anda di Pemicu
  4. Klik kanan, hapus centang "Pemicu Diaktifkan?"
Neil McGuigan
sumber
4
SET session_replication_role = replica;  

juga pekerjaan dosis untuk saya di Postgres 9.1. saya menggunakan dua fungsi yang dijelaskan oleh bartolo-otrit dengan beberapa modifikasi. Saya memodifikasi fungsi pertama agar berfungsi bagi saya karena namespace atau skema harus ada untuk mengidentifikasi tabel dengan benar. Kode baru adalah:

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;

maka saya cukup melakukan kueri pemilihan untuk setiap skema:

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