使用PostgreSQL,如何为以下场景管理序列(自动递增的整数id) -
表名为'business',其中包含'id'和更多列。
名为'users'的表格包含:
一个复合主键,由'business_id'和'id'组成,并且当我现在插入行时,'id'重置它为每个'business_id'计数。
一个简单的专栏名称。
类似于每个企业都有一个单独的序列。
当我运行以下查询时:
插入用户(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'
答案 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。