具有复合主键的序列

时间:2013-09-27 21:38:16

标签: postgresql primary-key auto-increment composite-primary-key

使用PostgreSQL,如何为以下场景管理序列(自动递增的整数id) -

表名为'business',其中包含'id'和更多列。

名为'users'的表格包含:

  1. 一个复合主键,由'business_id'和'id'组成,并且当我现在插入行时,'id'重置它为每个'business_id'计数。

  2. 一个简单的专栏名称。

  3. 类似于每个企业都有一个单独的序列。

    实施例

    当我运行以下查询时:

    插入用户(business_id,name)值(1,'a')

    插入用户(business_id,name)值(2,'b')

    插入用户(business_id,name)值(1,'c')

    我想最终得到以下'用户'表:

    business_id,id,name

    1,1,'a'

    1,2,'c'

    2,1,'b'

2 个答案:

答案 0 :(得分:2)

INSERT INTO [users]
(business_id, id)
FROM
(
SELECT 
ID - (SELECT MIN(ID) FROM [users] WHERE business_ID = B.ID) AS business_id
,(SELECT MAX(ID)+1 FROM [users] WHERE business_ID = B.ID) AS ID
FROM [businesses] B
)

如果您将此链接添加到要添加的新条目,则应提供复合键

新更新:

INSERT INTO [users]
(business_id, id, name)
VALUES
(
3
,ISNULL((SELECT MAX(ID)+1 FROM [users] WHERE business_ID = 3),1) AS ID
,'d'
)

答案 1 :(得分:2)

如果无法预测有多少(最多)用户与一个企业相关,则无法使用序列(即使可以,我也不会建议使用增量)。

如果您使用Postgres> = 9,您可以使用WITH来避免最大查询,方法是将计数器作为主表的列(或创建一个包含business_id对的新表(PK) ,next_id,如果你不能改变Businesses表)。

添加列next_id:

ALTER TABLE Businesses ADD COLUMN next_id bigint;
//update current rows with default value
ALTER TABLE Businesses ALTER COLUMN next_id SET DEFAULT 0;
ALTER TABLE Businesses ALTER COLUMN next_id SET NOT NULL;

要插入到Users中,请使用以下单个SQL语句,该语句将返回新的id。

With X as (
    Update Businesses
    set next_id=next_id+1 
    where id=:param_business_id
    Returning next_id)
Insert into Users (business_id,id,name)
Select :param_business_id, X.next_id ,:param_name
From X
Returning id

这会将第一个id插入为“1”,因为(第一个)returns子句返回更新的值。 或者,如果您使用包含ID的单独表,只需将“更新业务”替换为“更新MY_ID_TABLE”。 请注意,此解决方案不是vanilla SQL。