Composite key for a one-to-many relationship? - sql

For a store I have many store_offers which is a one-to-many relationship.
However, for a table
create table store (
id bigserial primary key
);
I can use a single primary key id (SQLfiddle):
create table store_offer (
id bigserial primary key,
store_id bigint not null,
constraint fk__store_offer__store
foreign key (store_id)
references store(id)
);
or a composite primary key (id, store_id) (SQLFiddle):
create table store_offer (
id bigserial not null,
store_id bigint not null,
constraint fk__store_offer__store
foreign key (store_id)
references store(id),
primary key(id, store_id)
);
My question is "what does make more sense here?". Imho the composite key should be the correct way to do it since a store_offer is actually "bound" to as store. But one can argue that this is already the case since the first version has a foreign key. On the other hand a store_offer primary key actually must not change once it's created. You have to create a new store_offer and delete the old one if you want discard one. But you cannot simply change store_id in the second approach.
So what is the correct answer here?

Using primary key(id, store_id) is a bad idea. This will make many queries more complicated and more prone to error. It sounds like what you are really trying to make is a many-to-many relationship between stores and offers. If this is the case you should have a store table with unique store_id as a primary key, an offer table with unique offer_id as a primary key and a store_offer table that has a primary key of store_id and offer_id.

Related

Storing foreign key linked in a separate table? SQL

So I went through Odoo database design and I saw that they stored the relationship between 2 tables in a separate table that doesn't have primary key. How are you able to do this? I want to replicate this kind of behavior in SQL Server. Is it auto-inserted?
A table should always have a primary key. Look at the thousands of questions on Stackoverflow that ask how to delete one of two identical rows in a database table.
You typically model m-to-n relationships between tables with a separate table that has foreign keys to both tables:
CREATE TABLE person (
person_id bigint PRIMARY KEY,
name text,
...
);
CREATE TABLE game (
game_id bigint PRIMARY KEY,
name text NOT NULL,
...
);
CREATE TABLE likes_to_play (
person_id bigint REFERENCES person NOT NULL,
game_id bigint REFERENCES game NOT NULL,
PRIMARY KEY (person_id, game_id)
);
CREATE INDEX ON likes_to_play (game_id);
The primary key on the table makes sure there are no superfluous double entries and backs one of the foreign keys. The other index is created for the other foreign key.

How to use two columns in a foreign key constraint

I have two tables:
Article
Subscription
In the Article table I have two columns that make up the primary key: id, sl. In the Subscription table I have a foreign key 'idsl`.
I use this constraint :
constraint FK_idsl
foreign key (idsl) references CSS_SubscriptionGroup(id, sl)
But when I run the query, I getting this error:
Number of referencing columns in foreign key differs from number of referenced columns, table X
In Article Table I have two fields that are the primary key: id,sl. In the Subscription Table I have a foreign key 'idsl`
This design is broken - it is apparent that the composite primary key in Article(id, sl) has been mangled into a single compound foreign key in table Subscription. This isn't a good idea.
Instead, you will need to change the design of table Subscription to include separate columns for both id and sl, of the same type as the Article Table, and then create a composite foreign key consisting of both columns, referencing Article in the same order as the primary key, e.g:
CREATE TABLE Article
(
id INT NOT NULL,
sl VARCHAR(50) NOT NULL,
-- Other Columns
CONSTRAINT PK_Article PRIMARY KEY(id, sl) -- composite primary key
);
CREATE TABLE Subscription
(
-- Other columns
id INT NOT NULL, -- Same type as Article.id
sl VARCHAR(50) NOT NULL, -- Same type as Article.sl
CONSTRAINT FK_Subscription_Article FOREIGN KEY(id, sl)
REFERENCES Article(id, sl) -- Same order as Article PK
);
Edit
One thing to consider here is that by convention a column named table.id or table.tableid should be unique, and is the primary key for the table. However, since table Article requires an additional column sl in the primary key, it implies that id isn't unique.
correct syntax for relation:
CONSTRAINT FK_OtherTable_ParentTable
FOREIGN KEY(OrderId, CompanyId) REFERENCES dbo.ParentTable(OrderId, CompanyId)
You must try like this:
constraint FK_idsl foreign key (id,sl) references CSS_SubscriptionGroup(id,sl)

Can a foreign key reference another foreign key

Is it possible to have a foreign key that references another foreign key in a different table, or can it only reference primary and unique keys?
A foreign key can reference any field defined as unique. If that unique field is itself defined as a foreign key, it makes no difference. A foreign key is just to enforce referential integrity. Making a field a foreign key doesn't change the field itself in any way. If it is a unique field, it can also be the target of another FK.
For example:
create table Table1(
PK int identity primary key,
...
);
create table Table2( -- 1-1 relationship with Table1
PKFK int primary key,
...,
constraint FK_Table2_1 foreign key( PKFK ) references Table1( PK )
);
create table Table3( -- relates to Table2
PKFKFK int primary key,
...,
constraint FK_Table3_2 foreign key( PKFKFK ) references Table2( PKFK )
);
I know of no DBMS where this is not the case. And I agree with Horse, there is nothing wrong with the practice.
Is it possible to have a foreign key that references another foreign key in a different table
Yes. In fact contrary to accepted answer, the referenced FK column doesn't even have to be unique! - at least in MySQL. see https://www.db-fiddle.com/f/6RUEP43vYVkyK2sxQQpBfj/0 for a demo of the same.
which brings up the question that if the FK is not unique in the parent table, then who is the parent row? The purpose of FKs is to establish parent-child relationship.

creating table having foreign key that reference another table

I am using PGAdminIII database.
I have one table named STOCKREGISTER which contains composite primary key consisting of three fields ie stockregisterId,applicationId and date.
I have to create another table STOCK which has a foreignkey field that reference the field stockregisterId of STOCKREGISTER.If I am trying to create STOCK table,an error message is shown.The error message is "there is no unique contraint matching keys for referenced table STOCKREGISTER".What another step I have to take next
this first table
CREATE TABLE stock_register
(
stock_register_id bigint NOT NULL,
application_id bigserial NOT NULL,
production_date date NOT NULL,
opening_bal bigint DEFAULT 0,
quantity_produced bigint,
total_quantity bigint
CONSTRAINT primarykey PRIMARY KEY (stock_register_id, application_id, production_date),
CONSTRAINT "foreignKey" FOREIGN KEY (application_id)
REFERENCES application (application_id) MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE NO ACTION
)
below is second table.Here I cannot make stock_register_id as a foreign key
CREATE TABLE Stock
(
stock_id bigint NOT NULL,
stock_register_id bigint,
dimension bigserial NOT NULL,
CONSTRAINT "stockid" PRIMARY KEY (stock_id)
)
I guess that syntax should be:
CREATE TABLE Stock
(
stock_id bigint NOT NULL,
stock_register_id bigint,
dimension bigserial NOT NULL,
CONSTRAINT "stockid"
FOREIGN KEY (stock_id)
REFERENCES stock_register (stock_register_id)
)
CREATE TABLE Stock
(
stock_id bigint NOT NULL,
stock_register_id bigint,
dimension bigserial NOT NULL,
CONSTRAINT primaryKey PRIMARY KEY (stock_id),
CONSTRAINT foreignKey FOREIGN KEY(stock_register_id)
REFERENCES stock_register (stock_register_id)
)
That should be everything you need. You'll also have to make sure the DB table engines, collations and charsets match up when using Foreign Keys.
For the unique constraint issue, there doesn't seem to be a problem with your stock_register_id PK in the stock_register table. Based on the name STOCKREGISTER in the error message I suspect it wasn't finding the table stock_register in your second Create statement.
What is a foreign key? A pointer to a specific record in another table.
How is a specific record in stock_register identified according to your DDL? By the unique combination of (stock_register_id, application_id, production_date).
Therefore stock_register_id = 1 could appear on a thousand different records so long as application_id and production_date are different.
Therefore, if all you have is a stock_register_id, there is no way to know which stock_register record it is pointing to and therefore no way for the DBMS to enforce the foreign key.
You must either add application_id and production_date to the stock table and make all three columns together the FK to the composite key on stock_register, or you must remove application_id and production_date from the PK on stock_register so the FK and PK columns match.

How do I create a Foreign Key?

I am working on my assignment. It has 8 tables. Each table has a primary key. What do i do to generate a foreign key to a table?
My reason for asking is that when I generate a primary key, a key symbol appears on the left.
What do i do to make something a foreign key?
Here's the MySQL docs for the subject -- you might wanna take a look at it. Basically, here's an example of what you do:
CREATE TABLE `table_1` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`name` VARCHAR(32) NOT NULL,
PRIMARY KEY (`id`)
)
CREATE TABLE `table_2` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`name` VARCHAR(32) NOT NULL,
`table1_id` INT(11) NOT NULL REFERENCES table_1(`id`)
)
This should basically make table_2.table1_id reference table_1.id as a foreign key.
The SQL to add a foreign key between table1 (the referencing table) and table2 (the primary table) is:
ALTER TABLE table1
ADD CONSTRAINT FOREIGN KEY table1_table2_FK
REFERENCES table2 (intId) ON (intTable2Id)
Your confusion is arising from the fact that you think a foreign key is a modified version of a primary key. It is not, it is a separate item.
For instance, CustomerID in the Customers table would have a primary key, but CustomerID in the Orders table would be a foreign key referencing (pointing back to) the primary key in the Customers table.
In the Customers table, the primary key serves to uniquely identify each customer. In the Orders table the foreign key on CustomerID serves to guarantee that each order belongs to an existing record from the customer table.
You can have the primary key without establishing any foreign keys, it will still serve it's role in identifying records. But you cannot have a foreign key without a primary key in a different table (or, in rare occurrences, in the same table) because the primary key name is part of the definition of the foreign key. And you can have as many foreign keys as you want in different tables (in rare cases in the same tables) pointing back to a single primary key.