Domanda

Using PostgreSQL, how do I manage a sequence (auto incremented Integer id) for the following scenario-

Table named 'businesses' which has 'id' and some more columns.

Table named 'users' which has:

  1. a composite primary key, composed of a 'business_id', and an 'id', and have the 'id' reset it's counting for each 'business_id' when I insert now rows.

  2. a simple column 'name'.

something like having a separate sequence per business.

Example

When I run the following queries:

insert into users (business_id, name) values (1, 'a')

insert into users (business_id, name) values (2, 'b')

insert into users (business_id, name) values (1, 'c')

I want to end up with the following 'users' table:

business_id, id, name

1, 1, 'a'

1, 2, 'c'

2, 1, 'b'

È stato utile?

Soluzione 2

You cannot use Sequences if you can´t predict how many (maximum) Users will be related to one businesses (and even if you can, I would not advise the use of increment that way).

If you use Postgres >=9 you can use WITH to avoid the max query, by placing the counter as a column of the master table (or create a new table that holds a pair business_id(PK),next_id if you can´t change the Businesses table).

Add the column 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;

To insert into Users, use the following single SQL statement, that returns the new id as a result.

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

This will insert the first id as "1", because (the first) returning clause returns the updated value. Or if you use a separate table that holds the ids, just replace the "Update Businesses" to the "Update MY_ID_TABLE". Notice that this solution is not vanilla SQL.

Altri suggerimenti

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
)

if you link this to the new entries you are adding, it should provide the composite key

New Update:

INSERT INTO [users]
(business_id, id, name)
VALUES
(
3
,ISNULL((SELECT MAX(ID)+1 FROM [users] WHERE business_ID = 3),1) AS ID
,'d'
)
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top