我有一个公司及其产品的数据库,我想要每个人 公司有一个单独的产品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之间的区别很大,我想让用户保持简单。
答案 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并更新表的值。我认为应该是非常高效的。