Postgres版本化的行

问题描述 投票:0回答:3

我想保留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中实现上述任何提示?

sql postgresql
3个回答
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
投票

默认情况下,唯一约束是“逐行”验证的,这就是您获得该错误的原因,但如果您将其定义为可延迟,则可以更改每个语句验证的约束:

alter table mytable
  add constraint pk_mytable primary key (id, version) 
  deferrable initially immediate;

该解决方案的缺点是,该主键不再能够成为外键的目标。


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)
© www.soinside.com 2019 - 2024. All rights reserved.