我目前正在尝试管理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
我现在需要的是一个功能,即:
我已经找到了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();
答案 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)