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

使用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

ERROR: duplicate key value violates unique constraint “tbl_test_pkey”
DETAIL: Key (testkey)=(2) already exists.

我需要在一个表中递增一列的每个值,这是复合唯一约束的一部分.我怎么能在一个声明中这样做?

谢谢 !

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

我有一个按类别组织的项目表.每个项目在该类别中都有一个特定的位置.

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)

请注意,(foo4,bar4)在category2中位于(foo3,bar3)之前.
现在,如果我想重新排序一个类别中的项目,我需要更新category_position …但是由于PK,我不能像使用sql Server一样使用Postgresql来移动值.

解决方法

这确实有点令人困惑,因为在语句级别上评估所有其他约束,在DML操作期间仅在每行级别上评估PK /唯一约束.

但是你可以通过将主键约束声明为可延迟来解决这个问题:

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;

延迟约束确实有一些开销,因此通过将其定义为最初立即,此开销保持最小.您可以在需要时使用set约束推迟约束评估.

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

相关文章

项目需要,有个数据需要导入,拿到手一开始以为是mysql,结果...
本文小编为大家详细介绍“怎么查看PostgreSQL数据库中所有表...
错误现象问题原因这是在远程连接时pg_hba.conf文件没有配置正...
因本地资源有限,在公共测试环境搭建了PGsql环境,从数据库本...
wamp 环境 这个提示就是说你的版本低于10了。 先打印ph...
psycopg2.OperationalError: SSL SYSCALL error: EOF detect...