Required to Declare Primary Keys on Junction Table? - sql

In a junction table made up of only foreign keys (e.g. ShopSupplier in the example below), must we also declare those columns as primary keys in the DDL create statement? If yes, what would be the point of doing so? I would argue that these are NOT primary keys in the example below
CREATE TABLE Shop
(
ShopID TEXT PRIMARY KEY UNIQUE,
ShopName TEXT
);
CREATE TABLE Supplier
(
SupplierID TEXT PRIMARY KEY UNIQUE,
SupplierName TEXT
);
CREATE TABLE ShopSupplier
(
ShopID TEXT,
SupplierID TEXT,
FOREIGN KEY(ShopID) REFERENCES Shop(ShopID),
FOREIGN KEY(SupplierID) REFERENCES Supplier(SupplierID)
);
The question again: Should I also declare PRIMARY KEY(ShopID, SupplierID) for the ShopSupplier table. If so, why? I would argue that there should be no primary key for that table.

Both columns are foreign key, because they are referencing to other tables. In the case that only single connection between specific rows of Shopand Supplier may exit, you can use a unique constraint or create a combined primary key:
CREATE TABLE ShopSupplier(
ShopID TEXT,
SupplierID TEXT,
PRIMARY KEY(ShopID, SupplierID),
FOREIGN KEY(ShopID) REFERENCES Shop(ShopID),
FOREIGN KEY(SupplierID) REFERENCES Supplier(SupplierID));
Then, both columns are foreign keys and belonging to the primary key.
In general setting the columns of a (pure) junction table as primary key isn't necessary. You may use it as a constraint to prohibit duplicates.

Related

Sql creating table consisting of keys from other tables

this is probably a simple question but I am quite new to SQL and databases, so I have been following this site: https://www.postgresqltutorial.com/postgresql-foreign-key/ to try and create a table that consist of primary keys from other tables.
Here I have the structure of the database in an excel overview. With colors showing the relations. i am having problems with the One-To-Many tables. As I get the same error every time "ERROR: column "id" referenced in foreign key constraint does not exist
SQL state: 42703".
The SQL query:
DROP TABLE IF EXISTS ingredient_to_unit_relations;
DROP TABLE IF EXISTS ingrediens;
CREATE TABLE ingrediens (
id serial,
name_of_ingredient varchar(255),
price_per_unit int,
PRIMARY KEY (id)
);
CREATE TABLE ingredient_to_unit_relations (
ingredient_relation_id int GENERATED ALWAYS AS IDENTITY,
PRIMARY KEY (ingredient_relation_id),
constraint Fk_ingredient_id
FOREIGN KEY (id)
REFERENCES ingrediens (id)
);
You need to define the column in order to declare it as a foreign key:
CREATE TABLE ingredient_to_unit_relations (
ingredient_relation_id int GENERATED ALWAYS AS IDENTITY,
ingredient_id int,
PRIMARY KEY (ingredient_relation_id),
constraint Fk_ingredient_id FOREIGN KEY (ingredient_id) REFERENCES ingrediens (id)
);
I might recommend some somewhat different naming conventions (I changed the name id in the table above):
CREATE TABLE ingredients (
ingredient_id int GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
name varchar(255),
price_per_unit int
);
CREATE TABLE ingredient_to_unit_relations (
ingredient_relation_id int GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
ingredient_id int,
CONSTRAINT Fk_ingredient_id FOREIGN KEY (ingredient_id) REFERENCES ingredients (ingredient_id)
);
Notes:
I am a fan of naming primary keys after the table they are in. That way, foreign keys and primary keys usually have the same name (and you can use using if you choose).
Avoid SERIAL. GENERATED ALWAYS AS IDENTITY is now recommended.
You can inline primary key constraints (as well as other constraints).
There is not generally a need to repeat the table name in a column (other than the primary key). So, name instead of name_of_ingredient.
Using int for a monetary column is suspicious. It doesn't allow smaller units. That might work for some currencies but in general I would expect a numeric/decimal type.

Is it possible to make a foreign key without the field being a primary key?

For example
create table Equipment (
Equipmenttype nvarchar(1,
Description nvarchar(10),
Primary Key (Equipmenttype)
)
Create table Room (
RoomID nvarchar(8),
Capacity numeric(3),
Roomtype(fk,nvarchar(2)
)
I want to create the following table...
create table RoomEquipment(
(RoomID here)
(Equipmenttype here)
but Equipmenttype is not a primary key.
You can create foreign key on columns that are PK or Unuque:
So you have to create a unique index on RoomID:
CREATE UNIQUE INDEX UI_Room_RoomID ON dbo.Room(RoomID);
Now you can create a foreign key in table RoomEquipment.
A FOREIGN KEY constraint does not have to be linked only to a PRIMARY KEY constraint in another table; it can also be defined to reference the columns of a UNIQUE constraint in another table.
Source: Foreign Key to non-primary key
Equipmenttype is a primary key, in its own table Equipment, and RoomID should be a primary key for Room.
So RoomEquipment is a standard many-to-many relationship table.

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.

could unique key ( not primary ) be a parent for declarative foreign key constraint

Naive question with the answer "No" , I believe, but still would like to ask.
Table_parent
pk_parent_surrogate
parent_natural_unique_key
Table_child
pk_child_surrogate
child_natural_NOT_unique
Is that true that the only possible declarative relationship among main database vendors is
pk_parent_surrogate ----------< pk_child_surrogate
and we can't have declarative constraint or foreign key in other words for pair
parent_natural_unique_key -------< child_natural_NOT_unique
My answer here is based on my MS SQL knowledge - although I believe the same answer is correct for ANSI standards as well, i'm not 100% sure...
YES - you CAN do this as long as you've got a unique constraint on the column in your parent table that you want to use as the anchor column for the key.
You can create a FOREIGN KEY constraint as part
of the table definition when you create a table.
If a table already exists, you can add a
FOREIGN KEY constraint, provided that the
FOREIGN KEY constraint is linked to an existing
PRIMARY KEY constraints or UNIQUE constraint in
another, or the same, table. A table can contain
multiple FOREIGN KEY constraints.
And as an example of this sort of key...
use tempdb
CREATE TABLE parent(
pk int identity primary key,
candidate_key int unique not null)
CREATE TABLE child(
pk int identity primary key,
join_key int references parent(candidate_key))
See here for more information.
Try code like this:
create table testunique (id int identity(1,1) primary key, otherid int)
go
create unique index ixOther on testunique(otherid)
go
create table testFK (id int identity(1,1) primary key, someid int)
go
alter table testFK add constraint fkTest foreign key (someid) references testunique(otherid)
Rob