我想在Postgres的行级中保留版本
表
Column | Type | Modifiers
------------+--------------------------+----------------------------------
id | integer | not null
version | integer | not null default 0
Indexes:
"mytable_pk" PRIMARY KEY, btree (id, version)
我打算使用版本0作为当前版本。
一个例子:
最初:
INSERT INTO mytable(id, version) VALUES(1, 0);
然后
UPDATE mytable SET version = version + 1 where id = 1;
INSERT INTO mytable(id, version) VALUES(1, 0);
然后
UPDATE mytable SET version = version +1 where id = 1;
出现错误
ERROR: duplicate key value violates unique constraint "mytable_pk"
DETAIL: Key (id, version)=(1, 1) already exists.
我在Mysql中使用此模式没有问题。 关于如何在Postgres中实现上述目标的任何提示?
答案 0 :(得分:2)
这是一个已知问题,在某些数据库中具有唯一约束。这是一种解决方法:
UPDATE mytable
SET version = - (version + 1)
WHERE id = 1;
UPDATE mytable
SET version = - version
WHERE id = 1 AND version < 0;
您也许还可以使用ORDER BY
来解决此问题:
UPDATE mytable
SET version = version + 1
WHERE id = 1
ORDER BY version DESC;
答案 1 :(得分:1)
默认情况下,唯一约束被“逐行”验证,这就是为什么会出现该错误的原因,但是如果您将其定义为可延迟的,则可以更改每个语句要验证的约束:
alter table mytable
add constraint pk_mytable primary key (id, version)
deferrable initially immediate;
该解决方案的缺点是,该主键不再是外键的目标。
答案 2 :(得分:0)
postgresql的版本是什么?我在9.5上进行了测试,一切正常。
postgres=# select version();
version
-------------------------------------------------------------------------------------------------------------------
PostgreSQL 9.5.14 on x86_64-pc-linux-gnu, compiled by gcc (Ubuntu 5.4.0-6ubuntu1~16.04.10) 5.4.0 20160609, 64-bit
(1 row)
postgres=# \d mytable
Table "public.mytable"
Column | Type | Modifiers
---------+---------+--------------------
id | integer | not null
version | integer | not null default 0
Indexes:
"mytable_pkey" PRIMARY KEY, btree (id, version)
postgres=# INSERT INTO mytable(id, version) VALUES(1, 0);
INSERT 0 1
postgres=# UPDATE mytable SET version = version + 1 where id = 1;
UPDATE 1
postgres=# INSERT INTO mytable(id, version) VALUES(1, 0);
INSERT 0 1
postgres=# UPDATE mytable SET version = version +1 where id = 1;
UPDATE 2
postgres=# select * from mytable ;
id | version
----+---------
1 | 2
1 | 1
(2 rows)