我想保留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中实现上述任何提示?
这是一些在某些数据库中具有唯一约束的已知问题。这是一个解决方法:
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;
默认情况下,唯一约束是“逐行”验证的,这就是您获得该错误的原因,但如果您将其定义为可延迟,则可以更改每个语句验证的约束:
alter table mytable
add constraint pk_mytable primary key (id, version)
deferrable initially immediate;
该解决方案的缺点是,该主键不再能够成为外键的目标。
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)