管理postgresql中的修订

时间:2014-03-25 12:19:41

标签: function postgresql triggers sequence

我目前正在尝试管理postgreSql数据库中数据集的修订。我想使用的表具有以下结构:

CREATE TABLE dataset (
   id BIGSERIAL PRIMARY KEY,
   revision INTEGER NOT NULL,
   object_id BIGINT NOT NULL
);

id字段是唯一的自动增量标识符。 object_id应该是对象的标识符,而revision会跟踪修订:

id | object_id | revision
-------------------------
 1 |         1 |        1
 2 |         2 |        1
 3 |         1 |        2
 4 |         1 |        3
 5 |         3 |        1
 6 |         4 |        1 

我现在需要的是一个功能,即:

  1. 如果未提供object_id,则设置自动增量object_id并将版本设置为1.
  2. 如果提供了object_id,则为此object_id设置自动增量修订。
  3. 我已经找到了this answer,但这并没有真正解决为object_id创建连续修订的问题,也没有解决自动创建连续object_id的问题。

    修改

    我会做类似以下的事情,但这感觉不太舒服:

    CREATE OR REPLACE FUNCTION update_revision() RETURNS TRIGGER LANGUAGE plpgsql AS
    $$
    BEGIN
        IF tg_op='INSERT' THEN
            IF NEW.object_id != NULL THEN
                NEW.object_id = SELECT nextval(object_id_seq_id);
                NEW.revision = 1;
            ELSE
                NEW.revision = SELECT MAX(revision)+1 FROM dataset WHERE spot_id = NEW.spot_id;
            END IF;
        END IF;
    
        RETURN NEW;
    END;
    $$;
    
    CREATE TRIGGER update_revision BEFORE INSERT OR UPDATE ON dataset
        FOR EACH ROW EXECUTE PROCEDURE update_revision();
    

1 个答案:

答案 0 :(得分:2)

制作(object_id, revision) unique。 BTW为什么他们不是primary key

create table dataset (
    id bigserial primary key,
    object_id bigint not null,
    revision integer not null,
    unique (object_id, revision)
);

create or replace function include_revision (_object_id integer)
returns dataset as $$
    with object_id as (
        select coalesce(max(object_id), 0) + 1 as object_id
        from dataset
    ), revision as (
        select coalesce(max(revision), 0) + 1 as revision
        from dataset
        where object_id = _object_id
    )
    insert into dataset (object_id, revision)
    select
        coalesce(_object_id, (select object_id from object_id)),
        (select revision from revision)
    returning *
    ;
$$ language sql;

object_id设置为coalesce(_object_id, (select object_id from object_id)),也就是说,只有当_object_id为空时才会使用计算出的max(object_id)

测试:

select include_revision(null);
 include_revision 
------------------
 (1,1,1)

select include_revision(1);
 include_revision 
------------------
 (2,1,2)

select include_revision(null);
 include_revision 
------------------
 (3,2,1)