Postgresql

如何防止觸發器覆蓋顯式設置的值?

  • January 10, 2022

我試過這個但沒有用,因為NEW.updated從來沒有NULL(我想NEW除了更新語句中的值之外,還填充了目前行中的值?):

create temp table test (
   created  TIMESTAMPTZ NOT NULL DEFAULT now(),
   updated  TIMESTAMPTZ NOT NULL DEFAULT now()
);

CREATE FUNCTION update_timestamp() RETURNS TRIGGER AS
$$
BEGIN
   IF NEW.updated IS NOT NULL THEN
       NEW.updated := now();
   END IF;
   RETURN NEW;
END;
$$ LANGUAGE plpgsql;

CREATE TRIGGER asdf BEFORE UPDATE ON test
FOR EACH ROW EXECUTE PROCEDURE update_timestamp();

NEW.updated := now();僅當updated未在更新語句中明確設置時,如何才能設置它?updated這樣當我想手動設置列時觸發器不會覆蓋我(例如updated=updated)。

OLD包含表中的目前值,NEW這些值就像它們在UPDATE.

如果NEW.updated IS DISTINCT FROM OLD.updated,則很明顯,該語句(或先前的觸發器)updated必須已更改。UPDATE

如果NEW.updated IS NOT DISTINCT FROM OLD.updated,您無法知道語句中是否updated指定了-可能已設置為與之前相同的值。UPDATE``UPDATE``updated

所以你能得到的最好的就是

IF NEW.updated IS NOT DISTINCT FROM OLD.updated THEN
  NEW.updated := current_timestamp;
END IF;

如果你有類似的東西,這不會做你想做的事SET updated = updated,但沒有補救辦法。

一個笨拙的解決方案,直到出現更好的東西。像這樣使用它:如果你的意思是updated=updated,那麼你寫updated=NULL

create temp table test (
   created  TIMESTAMPTZ NOT NULL DEFAULT now(),
   updated  TIMESTAMPTZ
);

CREATE OR REPLACE FUNCTION update_timestamp() RETURNS TRIGGER AS
$$
BEGIN
   IF NEW.updated IS NULL THEN
       IF OLD.updated IS NULL THEN -- first time updating this record
           NEW.updated := now();
       ELSE -- use updated=NULL as workaround for updated=updated
           NEW.updated := OLD.updated;
       END IF;
   ELSE
       NEW.updated := now();
   END IF;
   RETURN NEW;
END;
$$ LANGUAGE plpgsql;

引用自:https://dba.stackexchange.com/questions/245326