2011-01-12 71 views
3

我有一個數據庫與公司及其產品,我想爲每個 公司有一個單獨的產品id序列。postgresql公司id爲基礎的序列

我知道postgresql無法做到這一點,唯一的辦法是爲每家公司分別設置一個序列,但這很麻煩。

予想到的解決方案有一個單獨的表來保存序列

CREATE TABLE "sequence" 
(
    "table" character varying(25), 
    company_id integer DEFAULT 0, 
    "value" integer 
) 

「表」將是霍爾特爲序列表的名稱,諸如產品,類別等等

和值將保存將用於插入的product_id的實際序列數據

我將使用UPDATE ... RETURNING value;獲得產品編號

我在想這個解決方案是否高效?

使用行級別鎖定,只有同一公司的用戶在同一個表中添加行將不得不等待獲得一個鎖,我認爲這可以減少競爭條件問題。

有沒有更好的方法來解決這個問題?

我不想爲所有公司使用產品表的順序,因爲產品ID的差別會很大,我想讓用戶保持簡單。

回答

3

你可以只嵌入在你的公司表計數器:

CREATE TABLE companies (
    id   SERIAL PRIMARY KEY, 
    name  TEXT, 
    product_id INT DEFAULT 0 
); 

CREATE TABLE products (
    company  INT REFERENCES companies(id), 
    product_id INT, 
    PRIMARY KEY (company, product_id), 

    name  TEXT 
); 

INSERT INTO companies (id, name) VALUES (1, 'Acme Corporation'); 
INSERT INTO companies (id, name) VALUES (2, 'Umbrella Corporation'); 

然後,使用UPDATE ...返回獲取下一個產品ID爲特定公司:

> INSERT INTO products VALUES (1, (UPDATE companies SET product_id = product_id+1 WHERE id=$1 RETURNING product_id), 'Anvil'); 
ERROR: syntax error at or near "companies" 
LINE 1: INSERT INTO products VALUES (1, (UPDATE companies SET produc... 
              ^

哦不一!看來你不能(從PostgreSQL 9.1devel)使用UPDATE ... RETURNING作爲子查詢。

好消息是,這不是問題!只要創建一個存儲過程,做增量/返回部分:

CREATE FUNCTION next_product_id(company INT) RETURNS INT 
AS $$ 
    UPDATE companies SET product_id = product_id+1 WHERE id=$1 RETURNING product_id 
$$ LANGUAGE 'sql'; 

現在插入是小菜一碟:

INSERT INTO products VALUES (1, next_product_id(1), 'Anvil'); 
INSERT INTO products VALUES (1, next_product_id(1), 'Dynamite'); 
INSERT INTO products VALUES (2, next_product_id(2), 'Umbrella'); 
INSERT INTO products VALUES (1, next_product_id(1), 'Explosive tennis balls'); 

一定要使用相同的公司ID在這兩個產品價值和參數爲next_product_id(company INT)

+0

請注意,這是不(據我所知)原子:companies.product_id可能會增加沒有相應的插入產品。 – 2014-09-22 17:28:23

0

根據您擁有的公司數量,您可以爲每家公司創建一個序列。通過在product_id列中設置爲默認值的函數來查詢它。

或者,此函數可以簡單地執行SELECT FOR UPDATE並更新表的值。我認爲應該是非常高效的。