【发布时间】:2011-03-06 19:29:59
【问题描述】:
有没有办法从 Postgres 中的所有表中删除所有触发器?我知道我可以查看一个 pg_trigger 表,但它似乎没有包含足够的信息让我破译我添加到表中的触发器。
看起来外键约束也出现在 pg_trigger 表中,我不想删除它。我只想从我的表中删除用户创建的触发器并保留 FK。
有什么建议吗?
【问题讨论】:
标签: postgresql triggers
有没有办法从 Postgres 中的所有表中删除所有触发器?我知道我可以查看一个 pg_trigger 表,但它似乎没有包含足够的信息让我破译我添加到表中的触发器。
看起来外键约束也出现在 pg_trigger 表中,我不想删除它。我只想从我的表中删除用户创建的触发器并保留 FK。
有什么建议吗?
【问题讨论】:
标签: postgresql triggers
谢谢,詹姆斯。
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();
【讨论】:
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
我更喜欢这个(基于that)而不是@kuznetso3v 接受的答案,因为它让我有机会在使用复制粘贴执行它们之前检查DROP STATEMENTs:
SELECT 'DROP TRIGGER ' || trigger_name || ' ON ' || event_object_table || ';'
FROM information_schema.triggers
WHERE trigger_schema = 'public';
【讨论】:
看一下information_schema:
SELECT * FROM information_schema.triggers;
【讨论】:
更新:查看您想要的完整功能的真正解决方案。
好的,我想出了一个可以为我做这件事的函数:
创建或替换函数 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();这将删除您的公共架构中的任何触发器。
【讨论】:
只需级联删除您创建触发器时使用的语言。
比如我在plpgsql中创建了触发器,所以下面的查询会瞬间删除所有的触发器-
DROP LANGUAGE plpgsql CASCADE;
【讨论】:
最简单的方法是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。
【讨论】:
您可以从这个查询开始,查找外部触发器名称:
select * from pg_trigger t,pg_proc where
pg_proc.oid=t.tgfoid
【讨论】:
上面的答案仍然有缺陷,因为不需要两个循环。
可以通过以下方式完成:
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;
【讨论】:
我对旧答案的解决方案进行了两项改进:
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();
【讨论】: