如何在 PostgreSQL 中编写一个触发器,使其仅在定义触发器的表 x 更改后在事务结束时调用一次?因此,触发器不应为每一行或每个语句触发,而应仅在事务的所有语句执行完毕后触发一次。
(背景是,我想保存一些表上次更改时的时间戳。)
解决此问题的一种可能方法是使用延迟触发器和临时表。
假设您将时间戳存储在如下表中:
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();