【问题标题】:Accessing transaction context in a Postgres trigger在 Postgres 触发器中访问事务上下文
【发布时间】:2019-09-12 19:03:02
【问题描述】:

我有一个Postgres 11.3 数据库,上面有很多触发器。这些触发器是通过SQLAlchemy 的一些元编程自动生成的,并且基本上将每个CREATE/UPDATE/DELETE 操作包装在每条记录上,存储它的“版本”。这个过程是完全自动的,不需要最终用户付出任何努力。

我希望能够将user_id 外键添加到我的versions 表中。这是user_id,就像在应用程序用户中一样,不是正在执行事务的连接的 postgres/系统。该字段需要应用调用方法提供。

我最初的尝试涉及为每个表自动执行一组存储过程/postgres 函数。这可行,但我无法找到从当前事务访问 context 的方法。下面是一些伪代码来演示:

CREATE OR REPLACE FUNCTION delete_address(resource_id INTEGER, user_id INTEGER)
    RETURNS INTEGER as
    $BODY$
        DECLARE
            context USER_ID INTEGER; // something like this magical context keyword
        BEGIN
            USER_ID = user_id;

            DELETE FROM address WHERE id = resource_id;

            RETURN 1;
        END;
    $BODY$
    LANGUAGE plpgsql;

在此表的DELETE 触发器中:

CREATE OR REPLACE FUNCTION update_address_history_on_delete()
    RETURNS trigger AS
    $BODY$
    BEGIN
        UPDATE "versions"
        SET 
          date_archived = now()::timestamp,
          user_id = context USER_ID  // theres that magical context keyword again
        WHERE
            resource_id = OLD.id;
        RETURN OLD;
    END
    $BODY$
    LANGUAGE plpgsql

您将在这个假设中看到,我试图在单个事务的上下文中访问本质上是词法范围/闭包的值。

这是可能的,还是有其他方法可以解决这样的问题?

干杯!

【问题讨论】:

    标签: postgresql database-trigger


    【解决方案1】:

    您可以使用事务本地 custom configuration variable 来做到这一点。

    delete_address() 函数中的变量分配为:

    PERFORM set_config('my_vars.user_id', user_id, true);
    

    ...并使用以下方法检索触发器中的值:

    current_setting('my_vars.user_id')
    

    【讨论】:

    • 太棒了,谢谢。对于任何想要将其指定为特定于事务的人,我们可以在这里:postgresql.org/docs/11/functions-admin.html。请注意,它需要句号“。”分隔,所以“exciting.variable”可以工作,但“excitingvariable”不会
    猜你喜欢
    • 1970-01-01
    • 2011-10-08
    • 2023-04-07
    • 1970-01-01
    • 2017-01-30
    • 1970-01-01
    • 1970-01-01
    • 2012-06-15
    • 1970-01-01
    相关资源
    最近更新 更多