postgresql公司基于id的序列

时间:2011-01-12 18:42:33

标签: postgresql insert conditional-statements sequence race-condition

我有一个公司及其产品的数据库,我想要每个人 公司有一个单独的产品ID序列。

我知道postgresql无法做到这一点,唯一的办法就是为每家公司设一个单独的序列,但这很麻烦。

我想到了一个解决办法,有一个单独的表来保存序列

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

“table”将记录序列的表名,例如产品,类别等。

和value将保存将在insert

上用于product_id的实际序列数据

我将使用UPDATE ... RETURNING值;获得产品ID

我想知道这个解决方案有效吗?

使用行级锁定,只有同一公司的用户在同一个表中添加行才必须等待获取锁定,我认为这可以减少竞争条件问题。

有没有更好的方法来解决这个问题?

我不想为所有公司使用产品表序列,因为产品ID之间的区别很大,我想让用户保持简单。

2 个答案:

答案 0 :(得分: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 ... RETURNING获取给定公司的下一个产品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');

请务必在产品价值和next_product_id(company INT)的参数中使用相同的公司ID。

答案 1 :(得分:0)

根据您拥有的公司数量,您可以为每家公司创建序列。通过在product_id列上设置为默认值的函数进行查询。

或者,此函数可以简单地执行SELECT FOR UPDATE并更新表的值。我认为应该是非常高效的。