如何在PostgreSQL中暂时禁用触发器?

Dav*_*itt 117 postgresql triggers bulkinsert

我是批量加载数据,并且可以在事后比以逐行为基础更便宜地重新计算所有触发器修改.

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

zyz*_*zof 144

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

SET session_replication_role = replica;
Run Code Online (Sandbox Code Playgroud)

这会禁用当前会话的触发器.

要为同一会话重新启用:

SET session_replication_role = DEFAULT;
Run Code Online (Sandbox Code Playgroud)

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

  • 此命令不会禁用约束触发器也很方便 (7认同)
  • 一个警告:根据 [运行时配置文档](https://www.postgresql.org/docs/10/static/runtime-config-client.html#GUC-SESSION-REPLICATION-ROLE) 和 [ALTER TABLE 文档] (https://www.postgresql.org/docs/10/static/sql-altertable.html)这适用于普通触发器,但不适用于那些使用“ENABLE REPLICA”或“ENABLE ALWAYS”设置的触发器。 (5认同)
  • 请注意,它还会禁用外键约束检查。 (4认同)
  • 我使用的是“10.4”,它似乎忽略了上述声明。 (3认同)
  • 真棒.让我的质量删除从30分钟到<1秒:) (2认同)
  • 我花了最后半小时徒劳地试图在我的测试环境中绕过"违反外键约束"错误,这就是它! (2认同)

Dav*_*itt 112

PostgreSQL知道ALTER TABLE tblname DISABLE TRIGGER USER命令,这似乎做我需要的.请参见ALTER TABLE.

  • 小心并发加载:`ALTER TABLE ... DISABLE TRIGGER USER`需要对表进行独占锁定. (13认同)
  • @WojtekKruszewski,我认为David意味着他可以通过使用一些先验知识(例如,如果触发器将在每一行中进行相同的更改,可以更有效地)通过触发器手动重新计算更改由单个UPDATE处理).我不认为他意味着你可以在任何情况下都这样做. (3认同)

Mis*_*ise 32

用于禁用触发器

ALTER TABLE table_name DISABLE TRIGGER trigger_name
Run Code Online (Sandbox Code Playgroud)

用于启用触发器

ALTER TABLE table_name ENABLE TRIGGER trigger_name
Run Code Online (Sandbox Code Playgroud)

  • 您也可以使用“all”:`ALTER TABLE table_name DISABLE TRIGGER all` (9认同)

bar*_*rit 7

SET session_replication_role = replica; 
Run Code Online (Sandbox Code Playgroud)

如果我通过pgAdmin中的表编辑器更改表,它在我的Linux机器上不能与PostgreSQL 9.4一起使用,如果我通过普通查询更改表,则无效.pg_trigger表中的手动更改也不能在没有服务器重启的情况下工作,但是像postgresql.nabble.com上的动态查询可以在DATABASE中启用/禁用所有触发器.当你需要一些调整时它可能很有用.

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

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;
Run Code Online (Sandbox Code Playgroud)

如果要使用特定触发器功能禁用所有触发器,可以是:

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;
Run Code Online (Sandbox Code Playgroud)

系统目录的 PostgreSQL文档


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

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

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


pub*_*oid 7

处理此问题的一种非常优雅的方法是创建一个处理数据库填充的角色并为该角色设置复制:

ALTER ROLE role_name SET session_replication_role = 'replica';
Run Code Online (Sandbox Code Playgroud)

这样您就可以使用该角色来填充数据,而不必担心禁用和重新启用触发器等。


Nei*_*gan 6

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

  1. 找到你的桌子
  2. 展开+
  3. 在触发器中查找触发器
  4. 右键单击,取消选中"Trigger Enabled?"


小智 6

SET session_replication_role = replica;  
Run Code Online (Sandbox Code Playgroud)

在 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;
Run Code Online (Sandbox Code Playgroud)

然后我只是为每个模式做一个选择查询:

SELECT disable_triggers(true,'public');
SELECT disable_triggers(true,'Adempiere');
Run Code Online (Sandbox Code Playgroud)