【问题标题】:Drop ALL triggers from Postgres DB?从 Postgres DB 中删除所有触发器?
【发布时间】:2011-03-06 19:29:59
【问题描述】:

有没有办法从 Postgres 中的所有表中删除所有触发器?我知道我可以查看一个 pg_trigger 表,但它似乎没有包含足够的信息让我破译我添加到表中的触发器。

看起来外键约束也出现在 pg_trigger 表中,我不想删除它。我只想从我的表中删除用户创建的触发器并保留 FK。

有什么建议吗?

【问题讨论】:

    标签: postgresql triggers


    【解决方案1】:

    谢谢,詹姆斯。

    Drop ALL triggers from Postgres DB? 中的函数仅删除第一个表中的匹配项,并在其他表中保留具有相同名称的触发器。这是固定的功能:

    CREATE OR REPLACE FUNCTION strip_all_triggers() RETURNS text AS $$ DECLARE
        triggNameRecord RECORD;
        triggTableRecord RECORD;
    BEGIN
        FOR triggNameRecord IN select distinct(trigger_name) from information_schema.triggers where trigger_schema = 'public' LOOP
            FOR triggTableRecord IN SELECT distinct(event_object_table) from information_schema.triggers where trigger_name = triggNameRecord.trigger_name LOOP
                RAISE NOTICE 'Dropping trigger: % on table: %', triggNameRecord.trigger_name, triggTableRecord.event_object_table;
                EXECUTE 'DROP TRIGGER ' || triggNameRecord.trigger_name || ' ON ' || triggTableRecord.event_object_table || ';';
            END LOOP;
        END LOOP;
    
        RETURN 'done';
    END;
    $$ LANGUAGE plpgsql SECURITY DEFINER;
    
    select strip_all_triggers();
    

    【讨论】:

    • 这是这个答案第二次帮助我,如果可以的话,我会再次 +1
    • information_schema 缺少 TRUNCATE 触发器,因此请使用以下内容:SELECT tgname AS trigger_name, relname AS event_object_table FROM pg_trigger INNER JOIN pg_class ON pg_class.oid = tgrelid
    • 我发布了自己正确处理 TRUNCATE 触发器的答案。 stackoverflow.com/a/57577258/644332
    【解决方案2】:

    我更喜欢这个(基于that)而不是@kuznetso3v 接受的答案,因为它让我有机会在使用复制粘贴执行它们之前检查DROP STATEMENTs:

    SELECT 'DROP TRIGGER ' || trigger_name || ' ON ' || event_object_table || ';'
    FROM information_schema.triggers
    WHERE trigger_schema = 'public';
    

    【讨论】:

    • 我们可以删除选择以实际删除它
    【解决方案3】:

    看一下information_schema:

    SELECT * FROM information_schema.triggers;
    

    【讨论】:

    • 从 information_schema.triggers 中选择 trigger_name;效果更好。
    【解决方案4】:

    更新:查看您想要的完整功能的真正解决方案。

    好的,我想出了一个可以为我做这件事的函数:

    创建或替换函数 strip_all_triggers() 将文本返回为 $$ DECLARE triggNameRecord 记录; 触发表记录记录; 开始 FOR triggNameRecord IN select distinct(trigger_name) from information_schema.triggers where trigger_schema = 'public' LOOP SELECT distinct(event_object_table) INTO triggTableRecord from information_schema.triggers where trigger_name = triggNameRecord.trigger_name; RAISE NOTICE '删除触发器:% on table:%',triggNameRecord.trigger_name,triggTableRecord.event_object_table; 执行“删除触发器”|| triggNameRecord.trigger_name || '开' || triggTableRecord.event_object_table || ';'; 结束循环; 返回“完成”; 结尾; $$ 语言 plpgsql 安全定义器; 选择 strip_all_triggers();

    这将删除您的公共架构中的任何触发器。

    【讨论】:

      【解决方案5】:

      只需级联删除您创建触发器时使用的语言。
      比如我在plpgsql中创建了触发器,所以下面的查询会瞬间删除所有的触发器-

      DROP LANGUAGE plpgsql CASCADE;
      

      【讨论】:

      • 你看起来像个高风险的人
      • 错误:无法删除语言 plpgsql,因为扩展 plpgsql 需要它提示:您可以改为删除扩展 plpgsql。
      【解决方案6】:

      最简单的方法是pg_dump -s 对象定义并过滤以CREATE TRIGGER 开头的行。

      类似

      ./pg_dump -s db_name | grep '^CREATE TRIGGER' | \
        while read _ _ triggername _; do \
          echo drop trigger "$triggername;"; \
        done
      

      (在 bash 中)应该可以工作(查看它然后在数据库中运行)。

      但也许你应该考虑alter table table_name disable trigger trigger_name

      【讨论】:

        【解决方案7】:

        您可以从这个查询开始,查找外部触发器名称:

        select * from pg_trigger t,pg_proc where
         pg_proc.oid=t.tgfoid
        

        【讨论】:

          【解决方案8】:

          上面的答案仍然有缺陷,因为不需要两个循环。

          可以通过以下方式完成:

          CREATE PROCEDURE _DropTableTriggers()
          AS
          $$
          DECLARE
              _rec    RECORD;
          BEGIN
              FOR _rec IN
                  SELECT  DISTINCT    event_object_table, trigger_name
                  FROM    INFORMATION_SCHEMA.triggers
              LOOP
                  EXECUTE 'DROP TRIGGER ' || _rec.trigger_name || ' ON ' || _rec.event_object_table || ';';
              END LOOP;
          END
          $$ LANGUAGE plpgsql SECURITY DEFINER;
          

          【讨论】:

            【解决方案9】:

            我对旧答案的解决方案进行了两项改进:

            • 添加了按触发器名称、表和架构过滤
            • 正确处理“截断”触发器(被原始解决方案忽略)

            CREATE OR REPLACE FUNCTION strip_all_triggers() RETURNS text AS $$ DECLARE
                triggRecord RECORD;
            BEGIN
                create temp table all_triggers on commit drop as (
                    SELECT tgname AS trigger_name, n.nspname as trigger_schema,  relname as trigger_table
                    FROM pg_trigger
                             JOIN pg_class ON pg_class.oid = tgrelid
                             JOIN pg_namespace n ON n.oid = pg_class.relnamespace);
            
                FOR triggRecord IN select distinct on (trigger_schema, trigger_table, trigger_name) trigger_schema, trigger_table, trigger_name from all_triggers
                                   where trigger_schema like 'public' and trigger_name like '%' -- MY FILTER
                    LOOP
                        RAISE NOTICE 'Dropping trigger: % on table: %.%', triggRecord.trigger_name, triggRecord.trigger_schema, triggRecord.trigger_table;
                        EXECUTE 'DROP TRIGGER ' || triggRecord.trigger_name || ' ON ' || triggRecord.trigger_schema || '.' || triggRecord.trigger_table || ';';
                    END LOOP;
            
                RETURN 'done';
            END
            $$ LANGUAGE plpgsql SECURITY DEFINER;
            
            select strip_all_triggers();
            

            【讨论】:

              猜你喜欢
              • 2019-02-25
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2012-08-02
              • 1970-01-01
              相关资源
              最近更新 更多