CREATE TABLE widget (
id serial PRIMARY KEY,
name text NOT NULL,
ordinal int NOT NULL UNIQUE
);
我有数据
id | name | ordinal
----+------+---------
1 | A | 1
2 | B | 2
3 | C | 3
我想将其更新为
id | name | ordinal
----+------+---------
1 | A | 3
2 | B | 2
3 | C | 1
尽可能少地接触记录(即不要重写整个记录集,不要启动不必要的触发器),更新ordinal
为目标值的普遍适用的方法是什么?
普通更新只会让我违反约束,即使它发生在单个语句中。
并且删除和重新创建唯一约束是昂贵的并且并发性差。
这似乎是一个足够普遍的问题,应该有一个很好的方法来做到这一点,我只是想不出。
将约束定义为可延迟的:
然后你可以在一个语句中更新它:
默认情况下是普通
UNIQUE
约束NOT DEFERRABLE
。在每一行之后检查唯一的违规行为。手册将其表述为:但它确实检查了每个单独的书面行。
如果您定义
UNIQUE
约束DEFERRABLE
(如提供的 a_horse),则会在每个 statement 之后检查唯一的违规行为。在这方面,同一查询中的多个 CTE 仍算作一条语句。如果您还实际将约束设置为
DEFERRED
,则对唯一违规的检查将推迟到每个事务之后。综合演示:
db<>在这里摆弄
进一步阅读: