【问题标题】:Postgres versioned rowsPostgres 版本化行
【发布时间】:2019-02-27 18:51:58
【问题描述】:

我想为 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


    【解决方案1】:

    这是一些数据库中唯一约束的已知问题。这是一个解决方法:

    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;
    

    【讨论】:

      【解决方案2】:

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

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

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

      【讨论】:

        【解决方案3】:

        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)
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2013-06-07
          • 2020-05-28
          • 1970-01-01
          • 2017-11-10
          • 1970-01-01
          • 2013-04-29
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多