Referencing a composite primary key
Foreign keys have to match the primary/unique key they reference column for column. Since the primary key of BOOKING_REFERENCE
is (REFERENCE_ID
, CUST_ID
), that means that the foreign key from BR_FLIGHT
to BOOKING_REFERENCE
must consist of 2 columns also. That means you need to add CUST_ID
to the BR_FLIGHT
table - either that or your BOOKING_REFERENCE
primary key is wrong and should just be (REFERENCE_ID
).
That said, it doesn't make sense to have foreign keys defined in both directions as you do. The "child" table should reference the "parent" and not vice versa.
SQL: Foreign key references a composite primary key
If you have a compound PK made up from three columns, then any child table that wants to establish a foreign key relationship must ALSO have all those 3 columns and use all 3 columns to establish the FK relationship.
FK-PK relationship is an all or nothing proposal - you cannot reference only parts of a primary key - either you reference all columns - or you don't reference.
CREATE TABLE Purchase
(
No_Installments int,
Rate int,
Person varchar(50) NOT NULL PRIMARY KEY,
First_Name varchar(20) NOT NULL,
Name varchar(20) NOT NULL,
Address varchar(50) NOT NULL,
CONSTRAINT PFK
FOREIGN KEY (First_Name, Name, Address)
REFERENCES Person (First_Name, Name, Address)
);
How to reference a composite primary key in SQL
We declare an SQL FK (FOREIGN KEY) constraint to say that a subrow value for a list of columns always appears elsewhere as a subrow value for a list of columns that forms an SQL PK (PRIMARY KEY) or UNIQUE NOT NULL. Declare it whenever it isn't already implied by other declarations. It must reference the column list in a declared SQL PK (PRIMARY KEY) or UNIQUE NOT NULL. So you must declare that in the referenced table, even if that's already implied by NOT NULLs and a smaller contained PK or UNIQUE NOT NULL.
So note that an SQL PK is not necessarily a PK in the relational sense of being unique but not containing a smaller unique column set, ie being a superkey not containing a smaller superkey, ie being a minimal/irreducible superkey, ie being a CK (candidate key).
Here, you might need to replace the buildingno
& roomno
FKs by one, (buildingno, roomno)
to Room
:
CONSTRAINT SESSION_FK12
FOREIGN KEY(BUILDINGNO,ROOMNO) REFERENCES ROOM(BUILDINGNO,ROOMNO)
That might be appropriate for the meanings of your tables--which in fact you don't give, so we can't know, we can only guess. Eg if buildingno
could also be declared PK or UNIQUE NOT NULL in Room, which when roomno IS NOT NULL
is actually consistent with and implies (buildingno, roomno)
could be declared PK or UNIQUE NOT NULL, maybe your FK is right but your Room
declarations are inadequate.
When a subrow value for a list of columns always appears elsewhere as a subrow value for a list of columns that is called an IND (inclusion dependency) constraint. There's no way to declare a non-FK IND in SQL; we must enforce by triggers. That also might be what you need for your design.
You could keep the FK from buildingno
to Building
, but it's implied by the FK I suggest and the FK in buildingno
on Room
referencing Building
.
referencing part of the composite primary key
Foreign Key Reference Composite Primary Key
You have a parent table with a composite primary key on columns (deviceID, deviceType
). If you want to create a child table, you would need to:
- create one column in the child table for each column that is part of the primary key in the parent table (
deviceID, deviceType
) - create a composite foreign key that references that tuple of columns to the corresponding column tuple in the parent table
Consider:
CREATE TABLE IF NOT EXISTS `data` (
`dataID` int(11) unsigned NOT NULL AUTO_INCREMENT,
`deviceID` int(11) unsigned NOT NULL,
`deviceType` int(10) unsigned NOT NULL,
`payload` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL,
PRIMARY KEY (`dataID`),
CONSTRAINT `fk_data_pk`
FOREIGN KEY (`deviceID`, `deviceType`)
REFERENCES `devices` (`deviceID`, `deviceType`)
ON DELETE CASCADE
);
NB: creating a composite foreign key is functionally different than creating two foreign keys, each pointing at one of the columns in the parent table.
Given this data in the parent table:
deviceID deviceType
1 0
2 1
If you create a separated foreign key on each column, they will allow you to insert a record in the child table with values like (1, 1)
, or (2, 0)
. The composite foreign key will not allow it, since these specific tuples do not exist in the source table.
REFERENCE ON COMPOSITE PRIMARY KEY
You need to put the constraint in a single reference:
CONSTRAINT fk_BOX FOREIGN KEY(CLIENT_CODE, BOX_CODE, BOX_NUMBER)
REFERENCES BOX(CLIENT_CODE, BOX_CODE, BOX_NUMBER)
However, I would encourage you to put an identity int primary key on BOX
, and use that for a foreign key reference. You can declare a UNIQUE
constraint on BOX(CLIENT_CODE, BOX_CODE, BOX_NUMBER)
to prevent duplicates.
referencing part of the composite primary key
When a subrow in one table has to be a subrow in another (referenced) table, that is an inclusion dependency (IND). Eg player team_id referencing team id (not a key in team). When there is an IND and the referenced subrow is a key, that is a foreign key (FK). Eg player person_id referencing person id (a key in person). In SQL a FOREIGN KEY declaration says that there is an IND and the referenced columns are unique. (Ie declared by either PRIMARY KEY or UNIQUE). (So it actually means "foreign superkey".) In SQL we would ideally declare an IND (when there isn't also a FK) by a CHECK constraint. (But DBMSes do not support CHECK well). Ie check for player that team_id is in team projected on id. But you tried to declare an SQL FK. It fails because, as the error message says, team id is not unique.
(Notice here the distinction commented between teams and their team ids. Because a team id doesn't identify a team, you should only speak of a team identified by a team id and club. OOP must distinguish not only between teams in the world and team ids (some kind of string) in the world but also "team_id" pointer/reference values of a programming language. It was commented that id" is a bad name because a team id alone doesn't identify a team. We could just use the term used in the world.)
But you actually want something stronger than both your player table team_id IND and player_id FK. Ie check for player that team_id is paired in club with a club_id that is paired in contract with a person_id that is person_id.
Such complicated constraints are actually unnecessary if your design involved, say, roster(club_id,team_id,player_id) and didn't have team_id in player and probably didn't have contract either.
No, we cannot "see" from a schema that "person references club through contract". (And that phrase is a poor way of expressing what you mean.) We cannot tell that from the tables and keys. Every table holds rows that satisfy some statement parameterized by its column names; you must give these statements. Eg for player: person [person_id] plays on a team identified by [team_id] & some club. You must also give all business rules that restrict what situations can arise. Eg: A person can be contracted to at most one club. A team belongs to at most one club. A user (nor we) cannot use the database without the statements and you (nor we) cannot determine the constraints without the statements and business rules. Write them out.
mySQL Composite Key, Primary Key, Unique Key and References to the composite key
PRIMARY KEY (CourseN, `Quarter`, DayTime),
FOREIGN KEY (CourseN) REFERENCES Course(CourseN)
In this construct, you are making a composite primary key with columns (CourseN, Quarter DayTime)
. This implies that any combination of values of these three columns must be unique in the table. Also, you indicate that CourseN
is a foreign key that references the synonym column in table Course
, so every value of column CourseN
in your referring table LocationNTime
must be present in the referred table Course
.
This looks like a valid set up, where LocationNTime
is like a dependent table of Course
(like a child table or the-like).
PRIMARY KEY (CourseN),
UNIQUE KEY(`Quarter`, DayTime),
FOREIGN KEY (CourseN) REFERENCES Course(CourseN)
Here, CourseN
is the primary key of the table, so each value in this column must be unique. But it is also a foreign key to Course
. This does not really make sense in terms of normalization: if each and every record in LocationNTime
relate to a unique record in Course
, then why create two tables instead of storing all the data in a single record in Course
?
On top of this, you are creating a unique constraint on (
Quarter, DayTime)
, hence signaling that the combination of values in these columns unique.
This design looks flawned.
Consider the following dataset:
CourseN Quarter DayTime
1 1 14:00:00
1 2 14:10:00
1 3 14:00:00
1 4 14:10:00
The first design will allow this dataset, while the second will not, since the are duplicates in CourseN
. The following dataset would not be allowed either, since there are duplicates in (Quarter, DayTime)
:
CourseN Quarter DayTime
1 1 14:00:00
2 2 14:10:00
3 1 14:00:00
4 2 14:10:00
I believe that the first design is probably what you need.
Finally: you seem to think that a column that has a foreign key constraint (here, LocationNTime(CourseN)
) needs to be UNIQUE
: this is not the case. The only thing it needs is an index (and MySQL creates it for you under the hood when you declare it anyway). It's the column that is referred by the foreign key (here Course(CourseN)
) that needs to unique.
How do I reference a composite primary key with a foreign key using MySQL
This is the problem with composite PKs. In fact, your autonumber topographic_region_id will be unique and you should use that for the PK, and the FK. topographic_region sounds like it is also unique so you should add a unique index to it.
Related Topics
Restoring a Database from .Bak File on Another Machine
Any Disadvantages to Bit Flags in Database Columns
Sql Server 2008 - How to Convert Gmt(Utc) Datetime to Local Datetime
SQL - Subquery in Aggregate Function
Using SQL Query to Find Details of Customers Who Ordered > X Types of Products
How to Use a Trim Function in SQL Server
Read Text File to Insert Data into Oracle SQL Table
Count Number of Occurrences for Each Unique Value
Creating a Table from a Query Using a Different Tablespace (Oracle Sql)
SQL Query of Multi-Member File on As400
Select 10 Rows Per Day with Order
How to Remove SQL Azure Data Sync Objects Manually
Comparison Operator in Pyspark (Not Equal/ !=)
Web-Based, Hosted Admin Tool for SQL Server Database Access
How to Get The First Day and The Last of Previous Month Using Sql