7

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

名为“businesses”的表,其中包含“id”和更多列。

名为“用户”的表具有:

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

  2. 一个简单的列“名称”。

就像每个企业有一个单独的序列一样。

例子

当我运行以下查询时:

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

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

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

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

业务 ID、ID、名称

1, 1, '一个'

1, 2, 'c'

2, 1, 'b'

4

2 回答 2

3
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'
)
于 2013-09-27T21:55:06.080 回答
2

如果您无法预测有多少(最大)用户将与一项业务相关,则不能使用序列(即使可以,我也不建议以这种方式使用增量)。

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

添加列 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;

要插入用户,请使用以下单个 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”,因为(第一个)返回子句返回更新后的值。或者,如果您使用保存 id 的单独表,只需将“更新业务”替换为“更新 MY_ID_TABLE”。请注意,此解决方案不是普通 SQL。

于 2014-11-05T11:38:30.417 回答