sql - 选择要更改的表
问题描述
因此,我们有时(过于频繁地)忘记将日志记录触发器添加到我们的某些表中。我现在正在尝试编写一个迁移,它将自动将触发器添加到所有缺少它们的表中。
但是,如何选择要编辑的表?
我可以获得我需要更新的所有表的名称
WITH
trigger_information AS (
SELECT schemata.table_name, triggers.trigger_name
FROM information_schema.triggers triggers
RIGHT JOIN information_schema."tables" schemata ON schemata.table_name = triggers.event_object_table
WHERE
schemata.table_schema = 'public'
),
tables_without_log_trigger AS (
SELECT DISTINCT table_name
FROM trigger_information ti1
WHERE NOT EXISTS (
SELECT *
FROM trigger_information ti2
WHERE ti2.table_name = ti1.table_name
AND ti2.trigger_name = 'log_action'
)
)
-- TODO: add triggers to all tables in `tables_without_log_trigger`
;
怎么办?
我正在寻找一种方法来做类似的事情:
WITH
trigger_information AS (
SELECT schemata.table_name, triggers.trigger_name
FROM information_schema.triggers triggers
RIGHT JOIN information_schema."tables" schemata ON schemata.table_name = triggers.event_object_table
WHERE
schemata.table_schema = 'public'
),
tables_without_log_trigger AS (
SELECT DISTINCT table_name
FROM trigger_information ti1
WHERE NOT EXISTS (
SELECT *
FROM trigger_information ti2
WHERE ti2.table_name = ti1.table_name
AND ti2.trigger_name = 'log_action'
)
)
DO $$
DECLARE
iterator CURSOR FOR SELECT * FROM tables_without_log_trigger;
next_table TEXT;
BEGIN
OPEN iterator;
LOOP
FETCH NEXT FROM iterator INTO next_table;
EXIT WHEN NOT FOUND;
CREATE TRIGGER log_action
AFTER INSERT OR UPDATE OR DELETE ON next_table
FOR EACH ROW EXECUTE PROCEDURE logging.log_action();
END LOOP;
CLOSE iterator;
END $$;
任何帮助,将不胜感激。
解决方案
我认为这会有所帮助,但如果没有,请毫不犹豫地告诉我:
with cte_all_existing_trigger as
(
select distinct ta.table_name
from information_schema."tables" ta
inner join information_schema.triggers tr
on tr.event_object_table = ta.table_name
where ta.table_schema = 'public'
and tr.trigger_name like ' log_action%'
)
select string_agg(' CREATE TRIGGER log_action
AFTER INSERT OR UPDATE OR DELETE ON '||c.table_name||'
FOR EACH ROW EXECUTE PROCEDURE logging.log_action();', chr(13))
from information_schema."tables" c
where c.table_name not in (select table_name from cte_all_existing_trigger)
and c.table_schema = 'public';
将其放在 do 部分并执行查询结果。
推荐阅读
- c# - 二进制操作 long vs int
- arrays - 自定义单元格在 TableView 中是全白的
- laravel - 用户 $user 在 Laravel 中做什么?
- node.js - nodejs api数据打印到网页而不是控制台
- java - 如何将 ObjectGraphMeasurer.measure(object) 的结果转换为字节?
- node.js - ERR_TOO_MANY_REDIRECTS 使用 connect-ensure-login 进行索引时
- c# - 如何将一个脚本中的所有布尔值设置为另一个脚本中的布尔值?
- php - 分组集合上的求和关系
- android - FirebaseRecyclerAdapter 检查 Id 是否存在于另一个表中
- javascript - 添加 jquery 函数的问题。文件不起作用