2016-11-08 61 views
0

問題如下,我可以根據特定列(此處爲business_uuid)的值自動增加(verification_number),以便verify_number根據business_uuid自身最高值增加1(1)驗證號碼的數量?根據PostgreSQL中列的值自動增加

數據庫看起來如下: 表:驗證

verification_id = integer, sequence (Primary Key) 
business_uuid = text 
verification_number = integer 

的verification_id是這個表的主鍵,我想verification_number跟隨它的這取決於它的最高值過濾僅適用於自己的汽車增量business_uuid。

business_uuid是每個業務的唯一標識符。

可能嗎?

+1

你能不能給樣本輸入和它的輸出? –

+0

您可以通過觸發功能自動填充值。 – AlexM

回答

0

如果你想verification_number保存到表,但有可能在查詢時創建它目前還不清楚:

select verification_id, business_uuid, 
    row_number() over(
     partition by business_uuid 
     order by verification_id 
    ) as verification_number 
from verification 

上述方法的問題是,verification_number會改變,如果行被刪除

Window functions

0

我認爲這是一個不好的設計,但如果你真的想要,你可以如下實現它:

  1. 創建一個唯一約束:

    ALTER TABLE verification 
        ADD CONSTRAINT verification_uuid_nr_unique 
         UNIQUE (business_uuid, verification_number); 
    

    通過這創造也將進行以下觸發功能更快的索引。

  2. 創建BEFORE觸發修改verification_number

    CREATE OR REPLACE FUNCTION veritrig() RETURNS trigger 
        LANGUAGE plpgsql AS 
    $$BEGIN 
        SELECT COALESCE(max(verification_number)+1, 1) INTO NEW.verification_number 
         FROM verification 
         WHERE business_uuid = NEW.business_uuid; 
        RETURN NEW; 
    END;$$; 
    
    CREATE TRIGGER veritrig 
        BEFORE INSERT OR UPDATE ON verification FOR EACH ROW 
        EXECUTE PROCEDURE veritrig(); 
    
  3. 插入新的價值觀是這樣的:

    INSERT INTO verification (business_uuid) VALUES ('42'); 
    

    然後,你的願望verification_number將被設置。

但是,併發有一個問題。

如果幾屆嘗試插入或同時更新表,你會得到這樣的錯誤:

ERROR: duplicate key value violates unique constraint "verification_uuid_nr_unique" 
DETAIL: Key (business_uuid, verification_number)=(43, 1) already exists. 

這是因爲,在併發修改的SELECT語句僅看到當前(承諾)表中的內容並可能錯誤地嘗試爲business_uuid插入相同的verification_number

沒有辦法避免鎖定表的缺點。但是,如果您收到這樣的錯誤,您可以簡單地重試交易,並且可能性會在下次有效。

0
CREATE OR REPLACE FUNCTION public.creaid(
    IN key_field text, 
    IN table_mane text, 
    OUT id integer) 
    RETURNS integer AS 
$BODY$ 
    DECLARE maxid INT; 
    BEGIN 
     EXECUTE 'SELECT max('||key_field||') FROM '||table_name INTO maxid; 
     IF maxid IS NULL THEN 
      id = 1; 
     ELSE 
      id = maxid + 1; 
     END IF; 
    END; 
$BODY$ 
LANGUAGE plpgsql VOLATILE 
COST 100; 

然後,您可以調用該函數作爲數據庫的每個表的每一個關鍵值的默認值,如下所示:

DEFAULT creaid('key_field'::text, 'table_name'::text)