【问题标题】:How do I temporarily disable triggers in PostgreSQL?如何在 PostgreSQL 中临时禁用触发器?
【发布时间】:2011-04-25 22:18:44
【问题描述】:

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

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

【问题讨论】:

    标签: postgresql triggers bulkinsert


    【解决方案1】:

    用于禁用触发器

    ALTER TABLE table_name DISABLE TRIGGER trigger_name
    

    用于启用触发器

    ALTER TABLE table_name ENABLE TRIGGER trigger_name
    

    【讨论】:

    • 您也可以为此使用“all”:ALTER TABLE table_name DISABLE TRIGGER all
    【解决方案2】:
    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');
    

    【讨论】:

      【解决方案3】:
      SET session_replication_role = replica; 
      

      如果我通过 pgAdmin 中的表编辑器更改表,它不适用于我的 Linux 机器上的 PostgreSQL 9.4,如果我通过普通查询更改表,则它可以工作。 pg_trigger 表中的手动更改在没有服务器重启的情况下也不起作用,但是像postgresql.nabble.com ENABLE / DISABLE ALL TRIGGERS IN 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;
      

      如果您想禁用具有特定触发功能的所有触发器,可能是:

      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;
      

      system catalogs 的 PostgreSQL 文档


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

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

      ALTER TABLE ... ENABLE ALWAYS TRIGGER ... - 触发器将始终触发(显然)

      【讨论】:

        【解决方案4】:

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

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

        【讨论】:

          【解决方案5】:

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

          SET session_replication_role = replica;
          

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

          为同一会话重新启用:

          SET session_replication_role = DEFAULT;
          

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

          【讨论】:

          • 太棒了。让我的大规模删除从 30 分钟缩短到
          • 这个命令不禁用约束触发器也很方便
          • 我花了半个小时徒劳地寻找一种方法来绕过我的测试环境中的“违反外键约束”错误,就是这样!
          • 一个警告:根据runtime config docsALTER TABLE docs,这将适用于普通触发器,但不适用于使用ENABLE REPLICAENABLE ALWAYS 设置的触发器。
          • 我在10.4,它似乎忽略了上述声明。
          【解决方案6】:

          PostgreSQL 知道ALTER TABLE tblname DISABLE TRIGGER USER 命令,这似乎可以满足我的需要。见ALTER TABLE

          【讨论】:

          • 那你如何“重新计算所有触发器修改”?
          • 小心并发加载:ALTER TABLE ... DISABLE TRIGGER USER 需要对表进行排他锁。
          • @WojtekKruszewski,我认为大卫的意思是他可以使用一些先验知识手动重新计算触发器会完成的更改(例如,如果触发器将在每行,可以通过单个 UPDATE 更有效地处理)。我不认为他的意思是你可以在任何情况下都这样做。
          • @zyzof 的解决方案更适合禁用所有触发器。
          猜你喜欢
          • 1970-01-01
          • 2016-10-10
          • 2010-09-12
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-11-15
          • 1970-01-01
          • 2021-12-03
          相关资源
          最近更新 更多