2014-03-25 78 views
1

我目前正在嘗試管理postgreSql數據庫中的數據集的修訂版。我想用表的結構如下:管理修訂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並將修訂爲1,如果沒有提供object_id。
  2. 如果提供了object_id,則爲此object_id設置自動遞增修訂版。

我已經找到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(); 

回答

2

(object_id, revision)unique。順便說一句,爲什麼他們不是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) 
+0

感謝這個答案,但我有一些問題此解決方案。 'dataset'表是一個簡化的例子,它將包含更多的列。不過,我認爲這可以通過使用NEW對象來解決,就像我在第一次思考中所做的那樣!我不明白爲什麼每次調用這個函數時不應該增加object_id,因爲如果一個'_object_id'被設置爲'coalesce(max(object_id),0)+ 1',給出。我看到它的作品,但我不明白爲什麼。最後,我想知道這是否是一種快速解決方案,因爲我相信知道「with」非常慢。 – Phidelux

+0

@Avedo'NEW'只存在觸發器功能。我不認爲你需要它。您可以將其他列作爲參數傳遞。檢查'object_id'的更新解釋。 –

+0

@Avedo你從哪裏得到'with'慢?這個不成立。 –