Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sequences with composite primary key

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'

like image 241
Alon Amir Avatar asked Sep 27 '13 21:09

Alon Amir


People also ask

What is composite primary key with example?

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.

Can a primary key be a composite?

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.

What is a composite combination 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 ...

Where is composite primary key used?

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.


2 Answers

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'
)
like image 52
Grantly Avatar answered Sep 29 '22 08:09

Grantly


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.

like image 29
atorres Avatar answered Sep 29 '22 08:09

atorres