Удалить ВСЕ триггеры из базы данных Postgres?

Есть ли способ сбросить ВСЕ триггеры из ВСЕХ таблиц в Postgres? Я знаю, что есть таблица pg_trigger, на которую я мог бы смотреть, но не похоже, что она содержит достаточно информации для того, чтобы расшифровать триггеры, которые я добавил в мои таблицы.

Также похоже, что внешние ограничения внешнего ключа отображаются в таблице pg_trigger, которую я НЕ хочу отбрасывать. Я просто хочу удалить созданный пользователем триггер из моих таблиц и сохранить FK.

Любые предложения?

Ответ 1

Спасибо, Джеймс.

Функция из Drop ALL триггеров из 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();

Ответ 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();

Это приведет к потере любого триггера в вашей общедоступной схеме.

Ответ 3

Просто каскад отбросит язык, на котором вы создали триггеры.
Например, я создаю триггеры в plpgsql, поэтому следующий запрос мгновенно удаляет все триггеры -

DROP LANGUAGE plpgsql CASCADE;

Ответ 4

Взгляните в information_schema:

SELECT * FROM information_schema.triggers;

Ответ 5

Простейшим будет определение объектов 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.

Ответ 6

Я предпочитаю это (на основе что) по принятому ответу @kuznetso3v, потому что он дает мне возможность проверить DROP STATEMENT перед тем, как выполнить их с помощью copy- вставить:

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

Ответ 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();