是否有可能(如何?)从 "after update" 触发器到 return 旧值

Is it possible (how?) to return old value from "after update" trigger

UPDATE "Users" 
SET "displayName" = 'new_name' 
WHERE id = 1 
RETURNING "displayName"

查询以上 returns NEW 值。 我想知道 OLD 更新后 displayName 的值。我知道可以:

 UPDATE ... 
 FROM SELECT ... 
 RETURNING ...

但我想使用 AFTER UPDATE 触发器。是否有可能 "return" 来自 AFTER UPDATE 的旧值以某种方式触发?如果是的话,这样的扳机体会是什么样子?

是的,但是这里根本不涉及触发器。只是一个普通的 UPDATE.

RETURNING 子句 returns 值基于行 更新后。但是您可以将旧行包含在 FROM 子句中并使用 thatPer documentation:

Any expression using the table's columns, and/or columns of other tables mentioned in FROM, can be computed. The new (post-update) values of the table's columns are used.

解决方案:

UPDATE "Users" x
SET    "displayName" = 'new_name' 
FROM  (SELECT id, "displayName" FROM "Users" WHERE id = 1 FOR UPDATE) y 
WHERE  x.id = y.id
RETURNING y."displayName"

详细解释:

  • Return pre-UPDATE Column Values Using SQL Only - PostgreSQL Version

如果我的 ORM 不允许 FROM 子句怎么办?

你确定吗?如果是这样,一个简单(更昂贵)的替代方法是 运行 两个语句:

BEGIN;
-- Retrieve old value first;
SELECT "displayName" FROM "Users" WHERE id = 1 FOR UPDATE;

UPDATE "Users"
SET    "displayName" = 'new_name' 
WHERE  id = 1;

COMMIT;

事务包装器 (BEGIN; ... COMMIT;) 和行上的锁 (FOR UPDATE) 是为了防止可能的并发写入。如果你是唯一一个写入 table 的人,或者如果偶尔有过时的“旧值”是可以的,你可以删除两者。除非在非常有竞争力的设置中,否则很少发生。

或者使用原始 SQL 绕过劣质 ORM。

我可以想象解决这个问题的技巧(比如添加一个更新前值为 "displayName" 的冗余列),但这种技巧听起来 非常糟糕的主意.只需使用标准功能即可。