如何临时禁用PostgreSQL中的触发器?


131

我正在批量加载数据,并且在事实之后比逐行便宜得多地重新计算所有触发器修改。

如何临时禁用PostgreSQL中的所有触发器?

Answers:


162

另外,如果您想禁用所有触发器,而不仅仅是禁用USER表上的触发器,则可以使用:

SET session_replication_role = replica;

这将禁用当前会话的触发器。

要为同一会话重新启用:

SET session_replication_role = DEFAULT;

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


2
太棒了 使我的大规模删除从30分钟缩短为<1秒:)
Dan Lenski 2014年

7
方便的是,此命令不会禁用约束触发器
bartolo-otrit 2015年

2
我花了最后一个半小时徒劳地寻找一种绕过测试环境中“违反外键约束”错误的方法,这就是事实!
Amalgovinus

一个警告:根据运行时配置文档ALTER TABLE文档,这将适用于普通触发器,但不适用于使用ENABLE REPLICA或设置的触发器ENABLE ALWAYS
beldaz

我正在进行,10.4似乎忽略了以上声明。
Stephane

128

PostgreSQL知道ALTER TABLE tblname DISABLE TRIGGER USER命令,这似乎可以满足我的要求。请参阅ALTER TABLE


然后,您如何“重新计算所有触发器修改”?
Wojtek Kruszewski 2014年

15
小心并发负载:ALTER TABLE ... DISABLE TRIGGER USER需要在表上具有排他锁。
Erwin Brandstetter,2014年

3
@WojtekKruszewski,我认为David的意思是他可以通过使用一些先验知识(例如,如果触发器将在每一行中进行相同的更改,则可以更有效地手动计算触发器的更改),例如由单个UPDATE处理)。我不认为他的意思是您可以在每种情况下都可以这样做。
Rauni Lillemets 2014年

1
@zyzof的解决方案更适合于禁用所有触发器。
uthomas'3

47

对于禁用触发器

ALTER TABLE table_name DISABLE TRIGGER trigger_name

对于启用触发器

ALTER TABLE table_name ENABLE TRIGGER trigger_name

您也可以为此使用“全部”:ALTER TABLE table_name DISABLE TRIGGER all
DenisNovac

8
SET session_replication_role = replica; 

如果我通过pgAdmin中的表编辑器更改表,则无法与Linux机器上的PostgreSQL 9.4一起使用;如果我通过普通查询更改表,则该方法无法使用。如果不重新启动服务器,pg_trigger表中的手动更改也将不起作用,但是像在postgresql.nabble.com上那样的动态查询也可以启用/禁用数据库中的所有触发器。当您需要一些调整时,它可能会很有用。

例如,如果您的表在特定的命名空间中,则可能是:

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;

如果要使用某些触发功能禁用所有触发,则可能是:

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文档


触发器触发过程还有另一个控制选项:

ALTER TABLE ... ENABLE REPLICA TRIGGER ...-触发器仅在复制模式下触发。

ALTER TABLE ...始终启用触发器...-触发器将始终触发(显然)


7

您还可以在pgAdmin(III)中禁用触发器:

  1. 找到你的桌子
  2. 展开+
  3. 在触发器中查找触发器
  4. 右键单击,取消选中“已启用触发?”。

4
SET session_replication_role = replica;  

在Postgres 9.1中也对我有用。我使用bartolo-otrit描述的两个功能,并进行了一些修改。我修改了第一个函数以使其对我有用,因为必须存在名称空间或架构才能正确识别表。新的代码是:

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;

然后我只是对每个模式进行选择查询:

SELECT disable_triggers(true,'public');
SELECT disable_triggers(true,'Adempiere');
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.