简体   繁体   English

模式中所有表的PL / PGSQL动态触发器

[英]PL/PGSQL dynamic trigger for all tables in schema

I am looking to automate each table update with an automatic update of the updated_at column. 我希望自动更新每个表更新与updated_at列的自动更新。 I am able to make this work for a specific table using a trigger. 我能够使用触发器为特定的表做这项工作。 But my main goal, which I can't find anywhere, is to create a function that dynamically grabs all the tables in the schema, and creates that same trigger and only changing the table name that the trigger is referencing to. 但是我无法在任何地方找到的主要目标是创建一个动态抓取架构中所有表的函数,并创建相同的触发器并仅更改触发器引用的表名。 For the life of me I can't figure it out. 对于我的生活,我无法弄清楚。

I believe this shouldn't be as tricky as I'm making it as ever table in our schema will have the exact same column name of 'updated_at'. 我相信这不应该像我一样狡猾,因为我们的架构中的表将具有完全相同的列名'updated_at'。

One solution that I tried and thought would work was turning the table schema into an array, and iterating through that to invoke/create the trigger each iteration. 我尝试过并考虑过的一个解决方案是将表模式转换为数组,并迭代遍历每次迭代调用/创建触发器。 But I don't have a ton of psql experience so I am finding myself googling for hours to solve this one little thing. 但是我没有大量的psql经验,所以我发现自己谷歌搜索了几个小时来解决这个小问题。

SELECT ARRAY (
            SELECT
                table_name::text
            FROM 
                information_schema.tables

            WHERE table_schema = 'public') as tables;

I have also tried: 我也尝试过:

DO $$
DECLARE
    t text;
BEGIN
    FOR t IN 
        SELECT table_name FROM information_schema.columns
        WHERE column_name = 'updated_at'    
    LOOP 
        EXECUTE format('CREATE TRIGGER update_updatedAt
                        BEFORE UPDATE ON %I
                        FOR EACH ROW EXECUTE PROCEDURE updated_at()',
                        t);
    END loop;
    END;
    $$ language 'plpgsql';

Procedure: 程序:

CREATE OR REPLACE FUNCTION updated_at()
RETURNS TRIGGER AS $$
BEGIN
    NEW.updated_at = now();
    RETURN NEW;
END;
$$ language 'plpgsql';

Your DO block works. 你的DO块有效。 The only problem with it is we can't have same Trigger name for multiple triggers. 唯一的问题是我们不能为多个触发器使用相同的触发器名称。 So, you can either add a table_name suffix/prefix for the Trigger name. 因此,您可以为触发器名称添加table_name后缀/前缀。

DO $$
DECLARE
    t text;
BEGIN
    FOR t IN 
        SELECT  table_name FROM information_schema.columns
             WHERE column_name = 'updated_at'    
    LOOP 


        EXECUTE format('CREATE TRIGGER update_updatedAt_%I
                        BEFORE UPDATE ON %I
                        FOR EACH ROW EXECUTE PROCEDURE updated_at()',
                        t,t);
    END loop;
    END;
$$ language 'plpgsql';

Additionally you may add a check to see if the trigger already exists in information_schema.triggers to be safe. 此外,您可以添加一个检查,以查看information_schema.triggers是否已存在触发器是安全的。

IF NOT EXISTS ( SELECT 1 from information_schema.triggers 
                     where trigger_name = 'update_updatedat_'|| t)                                                                                      
  THEN

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM