UPDATE "Users"
SET "displayName" = 'new_name'
WHERE id = 1
RETURNING "displayName"
上面的查询返回新值。
我希望在更新后知道displayName
的 OLD 值。我知道有可能:
UPDATE ...
FROM SELECT ...
RETURNING ...
但我想使用AFTER UPDATE
触发器。有可能"返回"来自AFTER UPDATE
的旧值会以某种方式触发?如果是这样的触发器体会是什么样子?
答案 0 :(得分:5)
是的,但此处涉及无触发器。只是一个简单的UPDATE
。
RETURNING
子句根据更新后的行返回值。但是您可以在FROM
子句中包含旧行,并使用 。 Per documentation:
可以计算使用表的列和/或
FROM
中提到的其他表的列的任何表达式。使用表格列的新(更新后)值。
解决方案:
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"
详细说明:
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
)用于防止可能的并发写入。如果您是唯一写入该表的人,或者偶尔过时的“旧值”可以,则可以删除这两者。除非竞争非常激烈,否则很少发生。
或者使用原始SQL绕过劣质ORM。
我可以设想解决这个问题的技巧(比如添加一个更新前的值为"displayName"
的冗余列),但这样的技巧听起来像非常糟糕的主意。只需使用标准功能。