ora*_*nge 4 postgresql subquery update unique-constraint
foo
在具有两列(id
和)的表中seq
,我想为seq
具有任意 . 的所有记录添加+1 seq > 4738
。计划是在seq=4739
所有seq > 4738
记录移动+1 后立即插入一条新记录。
这是桌子。
CREATE TABLE foo
(
id uuid NOT NULL,
seq integer NOT NULL,
CONSTRAINT seq_key UNIQUE (seq)
)
CREATE UNIQUE INDEX idx_id
ON foo
USING btree
(id);
CREATE UNIQUE INDEX idx_seq
ON foo
USING btree
(seq);
Run Code Online (Sandbox Code Playgroud)
我尝试通过以下查询实现 +1 转变。请注意,我使用子查询尝试> 4738
按降序更新记录(即假设 max seq=10000,则首先更新最后一条记录(10000->10001),然后更新倒数第二条记录(seq=10000
此时不存在,seq=9999
-> seq=10000
(没有违反约束),然后是 9998 -> 9999,...以避免在任何时候发生唯一的约束违反。但是,这假设更新查询是顺序执行的,而这似乎并不是发生的情况。
跑步时
UPDATE foo SET seq=anon_1.new_seq FROM (
SELECT foo.id AS id, foo.seq + 1 AS new_seq
FROM foo
WHERE foo.seq > 4738 ORDER BY foo.seq DESC
) AS anon_1 WHERE foo.id = anon_1.id
Run Code Online (Sandbox Code Playgroud)
我收到以下错误。
重复的键值违反了唯一约束“seq_key”详细信息:键(seq)=(7334)已存在。
显然,这是出乎意料的(因为约束在 之前已得到满足UPDATE
)。有什么我可以尝试解决问题的吗(不同的索引类型,只有约束,只有索引)?我注意到这个错误很大程度上取决于更新记录的数量。如果更新的记录较少,那么这个问题似乎不会发生(这可能暗示当有太多记录需要更新时会进行一些并行执行,这可能会交错并导致某种中间状态,其中约束/索引不是唯一的)更多的)。一些想法和想法将不胜感激。
小智 7
您需要创建可延迟约束而不是索引。
CREATE TABLE foo
(
id uuid NOT NULL primary key
seq integer NOT NULL,
CONSTRAINT seq_key UNIQUE (seq)
deferrable initially immediate --<< this
);
Run Code Online (Sandbox Code Playgroud)
通过将约束声明为可延迟,它将在 UPDATE 语句末尾(更准确地说:在事务末尾)而不是逐行检查。
归档时间: |
|
查看次数: |
4861 次 |
最近记录: |