仅在事务结束时执行一次的触发器

问题描述 投票:0回答:1

如何在 PostgreSQL 中编写一个触发器,使其仅在定义触发器的表 x 更改后在事务结束时调用一次?因此,触发器不应为每一行或每个语句触发,而应仅在事务的所有语句执行完毕后触发一次。

(背景是,我想保存一些表上次更改时的时间戳。)

postgresql triggers transactions
1个回答
0
投票

解决此问题的一种可能方法是使用延迟触发器和临时表。

假设您将时间戳存储在如下表中:

CREATE TABLE TABLE_CHANGE_LOG(
    TABLE_NAME   VARCHAR(255)                        NOT NULL,
    CHANGED_TIME TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL
);

对于触发器功能,我们需要一个临时表来跟踪每个更改的表,因此我们不会在

TABLE_CHANGE_LOG
中创建重复的条目。我们在
TABLE_CHANGE_LOG
中创建所需的日志条目,并在临时
UPDATE_FLAG
表中创建一行,以避免当前触发表的后续条目。

CREATE OR REPLACE FUNCTION TABLE_CHANGE_LOGGER_TRIGGER_FUNCTION()
    RETURNS TRIGGER
    LANGUAGE PLPGSQL
AS
$$
BEGIN
    CREATE TEMP TABLE IF NOT EXISTS UPDATE_FLAG(TABLE_NAME VARCHAR(255)) ON COMMIT DROP;
    IF (SELECT CASE WHEN COUNT(*) = 0 then 1 else 0 end 
        FROM UPDATE_FLAG WHERE TABLE_NAME = TG_TABLE_NAME)
    THEN
        INSERT INTO TABLE_CHANGE_LOG (TABLE_NAME) VALUES (TG_TABLE_NAME);
        INSERT INTO UPDATE_FLAG (TABLE_NAME) values (TG_TABLE_NAME);
    END IF;
    RETURN NEW;
END;
$$;

约束触发器。不幸的是,您想要记录的每个表都需要一个触发器。

CREATE CONSTRAINT TRIGGER TABLE_CHANGE_LOGGER_TRIGGER
    AFTER INSERT
    ON %YOUR_TABLE_NAME%
    DEFERRABLE INITIALLY DEFERRED
    FOR EACH ROW
EXECUTE FUNCTION TABLE_CHANGE_LOGGER_TRIGGER_FUNCTION();
© www.soinside.com 2019 - 2024. All rights reserved.