从Postgres DB中删除所有触发器?

时间:2010-06-22 12:46:18

标签: postgresql triggers

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

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

有什么建议吗?

9 个答案:

答案 0 :(得分:22)

谢谢,詹姆斯。

来自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 :(得分:2)

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

好吧,我想出了一个能为我做这个的功能:

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
        SELECT distinct(event_object_table) INTO triggTableRecord from information_schema.triggers where trigger_name = triggNameRecord.trigger_name;
        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;

    RETURN 'done';
END;
$$ LANGUAGE plpgsql SECURITY DEFINER;

select strip_all_triggers();

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

答案 2 :(得分:2)

只需级联删除您创建触发器的语言即可 例如,我在plpgsql中创建了触发器,因此以下查询会立即删除所有触发器 -

DROP LANGUAGE plpgsql CASCADE;

答案 3 :(得分:1)

查看information_schema:

SELECT * FROM information_schema.triggers;

答案 4 :(得分:1)

最简单的是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

答案 5 :(得分:0)

您可以从此查询开始,找出触发器名称:

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

答案 6 :(得分:0)

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

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

答案 7 :(得分:0)

由于不需要两个循环,因此最高答案仍然有缺陷。

可以通过以下方式完成:

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;

答案 8 :(得分:0)

我从较早的答案中对解决方案进行了两项改进:

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

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();