使用触发器更新行而不会导致无限循环
Updating a row with a trigger without causing an infinite loop
我有一个名为 updated
的列,旨在显示上次更改该列的时间。
我的第一次尝试是创建一个触发器,将 updated
列更改为 now()
返回的值。但是因为这个触发器发生在更新事件上,它导致了无限循环(更新更新列导致触发器触发)。
我也尝试过实施一个规则来达到类似的效果。
我无法想象这是我在调用和更新函数时被迫在应用层做的事情。那么如何更新该行的更新列而不导致无限循环?
我已经通过检查我正在更改的字段在其他应用程序中解决了这个问题,如果没有任何更改,那么我不会进行更新。如果您可以检查更新的列并且它在最后 N 秒内,请不要进行更新。这应该停止无限循环。选择你想要的数字 N,这样你就可以知道更新时间戳总是在 N 秒内。
使用这样的触发器:
CREATE OR REPLACE FUNCTION update() RETURNS trigger AS $$
BEGIN
IF NEW.updated = OLD.updated THEN
NEW.updated = NOW()
END IF;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER table_update
BEFORE UPDATE ON table
FOR EACH ROW EXECUTE PROCEDURE update()
这样你就不会陷入循环——你只更新一次值(在执行 UPDATE 之前),而且你也不会破坏值,如果出于某种原因你想设置 updated
显式(例如,从备份中导入旧数据时)。
我有一个名为 updated
的列,旨在显示上次更改该列的时间。
我的第一次尝试是创建一个触发器,将 updated
列更改为 now()
返回的值。但是因为这个触发器发生在更新事件上,它导致了无限循环(更新更新列导致触发器触发)。
我也尝试过实施一个规则来达到类似的效果。
我无法想象这是我在调用和更新函数时被迫在应用层做的事情。那么如何更新该行的更新列而不导致无限循环?
我已经通过检查我正在更改的字段在其他应用程序中解决了这个问题,如果没有任何更改,那么我不会进行更新。如果您可以检查更新的列并且它在最后 N 秒内,请不要进行更新。这应该停止无限循环。选择你想要的数字 N,这样你就可以知道更新时间戳总是在 N 秒内。
使用这样的触发器:
CREATE OR REPLACE FUNCTION update() RETURNS trigger AS $$
BEGIN
IF NEW.updated = OLD.updated THEN
NEW.updated = NOW()
END IF;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER table_update
BEFORE UPDATE ON table
FOR EACH ROW EXECUTE PROCEDURE update()
这样你就不会陷入循环——你只更新一次值(在执行 UPDATE 之前),而且你也不会破坏值,如果出于某种原因你想设置 updated
显式(例如,从备份中导入旧数据时)。