【问题标题】:PL/PGSQL dynamic trigger for all tables in schema模式中所有表的 PL/PGSQL 动态触发器
【发布时间】:2018-12-14 02:22:54
【问题描述】:

我希望通过自动更新 updated_at 列来自动更新每个表。我可以使用触发器为特定表完成这项工作。但是我在任何地方都找不到的主要目标是创建一个函数,该函数可以动态获取架构中的所有表,并创建相同的触发器,并且只更改触发器所引用的表名。对于我的生活,我无法弄清楚。

我相信这不应该像我做的那样棘手,因为我们架构中的表将具有完全相同的列名“updated_at”。

我尝试并认为可行的一个解决方案是将表模式转换为数组,并通过它进行迭代以在每次迭代时调用/创建触发器。但是我没有大量的 psql 经验,所以我发现自己在谷歌上搜索了几个小时来解决这个小问题。

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

            WHERE table_schema = 'public') as tables;

我也试过了:

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';

程序:

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

【问题讨论】:

    标签: sql arrays postgresql triggers psql


    【解决方案1】:

    您的DO 块有效。唯一的问题是我们不能为多个触发器使用相同的触发器名称。因此,您可以为触发器名称添加 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';
    

    此外,为了安全起见,您还可以添加检查以查看触发器是否已存在于 information_schema.triggers 中。

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

    【讨论】:

    • 那个人做到了!谢谢!!
    • @GaelicLaic:不客气。请务必查看编辑。
    • 我们不能为多个触发器使用相同的触发器名称。 我尝试将 update_updatedAt_%I 替换为 update_updatedAt 并它仍然有效。
    猜你喜欢
    • 1970-01-01
    • 2017-04-16
    • 1970-01-01
    • 1970-01-01
    • 2018-02-10
    • 1970-01-01
    • 2014-03-12
    • 2018-02-10
    • 1970-01-01
    相关资源
    最近更新 更多