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:
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.
a simple column 'name'.
something like having a separate sequence per business.
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'
A composite key, then, would be the combination of two keys. For example: the combination of house number and street might qualify as a composite key, given that the market listings are local. If so, then when someone searches using both the house number and the street, they should only get one single record returned.
A primary key that is made by the combination of more than one attribute is known as a composite key. In other words we can say that: Composite key is a key which is the combination of more than one field or column of a given table. It may be a candidate key or primary key.
A Composite Primary Key is created by combining two or more columns in a table that can be used to uniquely identify each row in the table when the columns are combined, but it does not guarantee uniqueness when taken individually, or it can also be understood as a primary key created by combining two or more ...
Composite keys in SQL prove to be useful in those cases where you have a requirement of keys that can uniquely identify records for better search purposes, but you do not possess any single unique column. In such cases, you must combine multiple columns to create a unique key.
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'
)
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With