PostgreSQL中的移位(更新)唯一列值

PostgreSQL中的移位(更新)唯一列值,sql,postgresql,sql-update,unique-constraint,Sql,Postgresql,Sql Update,Unique Constraint,使用MS SQL Server,以下功能可以正常工作: CREATE TABLE #temptable(mykey int primary key) INSERT INTO #temptable VALUES (1) INSERT INTO #temptable VALUES (2) UPDATE #temptable SET mykey=mykey+1 但是,使用PostgreSQL时,以下操作失败: CREATE TABLE pg_temp.tbl_test(testkey integ

使用MS SQL Server,以下功能可以正常工作:

CREATE TABLE #temptable(mykey int primary key)

INSERT INTO #temptable VALUES (1)
INSERT INTO #temptable VALUES (2)

UPDATE #temptable SET mykey=mykey+1
但是,使用PostgreSQL时,以下操作失败:

CREATE TABLE pg_temp.tbl_test(testkey integer primary key)

INSERT INTO pg_temp.tbl_test VALUES (1)
INSERT INTO pg_temp.tbl_test VALUES (2)

UPDATE pg_temp.tbl_test SET testkey=testkey+1
错误:重复的键值违反唯一约束“tbl_test_pkey” 详细信息:密钥(testkey)=(2)已存在

我需要增加一个表中一列的每个值,这是复合唯一约束的一部分。我如何在一份声明中做到这一点

谢谢


编辑:如果你想知道为什么这是有意义的(至少对我来说),这里有一个更完整的场景

我有一个项目分类表。每个项目在类别中都有特定的位置

category_id (PK) | category_position (PK) | item_attribute_1 | item_attribute_2
1 | 1 | foo | bar
1 | 2 | foo2 | bar2
2 | 1 | foo4 | bar4
2 | 2 | foo3 | bar3
此表包含以下数据:

category1 : (foo, bar), (foo2, bar2)
category2 : (foo4, bar4), (foo3, bar3)
请注意,在类别2中,(foo4,bar4)位于(foo3,bar3)之前。
现在,如果我想重新排序一个类别中的项目,我需要更新类别位置。。。但是由于PK,我不能像使用SQL Server那样使用PostgreSQL来移动值。

这确实有点令人困惑,因为所有其他约束都是在语句级别上计算的,在DML操作期间,只有PK/unique约束是在每行级别上计算的

但您可以通过将主键约束声明为可延迟来解决此问题:

create table tbl_test 
(
  testkey   INTEGER,
  constraint pk_tbl_test primary key (testkey) deferrable initially immediate
);

insert into tbl_test values (1), (2);

set constraints all deferred;

update tbl_test
   set testkey = testkey +1;
延迟约束确实有一些开销,因此通过将其定义为
初始立即
,可以将此开销保持在最小。您可以使用
设置约束
,在需要时推迟约束计算



然而,真正的问题是:为什么需要对主键值执行此操作?PK值没有任何意义,因此似乎没有必要增加所有值(无论使用的是何种DBMS)

解决方案,而不改变约束条件,因为
可延迟初始立即

UPDATE tbl_test t1 
SET    testkey = t2.testkey + 1 
FROM   (SELECT testkey 
    FROM   tbl_test 
    ORDER  BY testkey DESC) t2 
WHERE  t1.testkey = t2.testkey 

在线示例:

感谢您的回答;我在问题中添加了一个更完整的场景。我来看看你的解决方案。@personne3000:deferrable属性在约束级别上起作用,所以PK有多少列无关紧要。但把这个职位作为PK的一部分似乎是一个相当奇怪的设计。PK值应该是稳定的,不经常变化。每次插入新项目时必须更改PK值通常表示DB设计不好。但是我仍然希望对这些列保留唯一的约束,因为我不希望两个项目在同一类别中具有相同的位置。我确实有另一个pkey的候选元组(它有另一个唯一的约束);使用它会更好吗?@personne3000:如果你有一对“稳定”的PK列,那么我更喜欢它。您仍然可以在category\u id/position上定义可延迟的唯一约束(而不是索引!)。但是,如果要频繁地对位置重新编号,为什么首先需要唯一约束?当你对它重新编号时,你可以为每个项目分配唯一的位置。最后我使用了另一个元组作为主键,并按照你的建议对类别和顺序使用了一个可延迟的唯一约束。订单不会经常更新:仅当管理员决定更改某些项目的显示顺序时。我更喜欢保留唯一的约束,以确保我的数据在数据库级别有效。谢谢如果表格足够大,则会生成“错误:范围表格条目过多”。你知道如何克服它吗?