MYSQL - Cannot add foreign key constraint, but why? - mysql

I don't understand I get cannot add foreign key constraint when trying to run this code. I narrowed it down to the last line:
FOREIGN KEY (room_no) REFERENCES Classroom(room_no)
giving me this error, as when I delete it the code runs fine. Could someone explain the issue to me? This code is part of a much bigger code block, and I seem to run into the same problem later on.
Thank you!
CREATE TABLE Classroom (
building VARCHAR(100),
room_no SMALLINT UNSIGNED,
capacity SMALLINT UNSIGNED,
CONSTRAINT PK_Prereq PRIMARY KEY (building, room_no)
);
CREATE TABLE Section (
course_id INT UNSIGNED,
sec_id INT UNSIGNED,
semester SMALLINT UNSIGNED,
year SMALLINT UNSIGNED,
building VARCHAR(100),
room_no SMALLINT UNSIGNED,
time_slot_id INT UNSIGNED,
CONSTRAINT PK_Prereq PRIMARY KEY (course_id, sec_id, semester, year),
FOREIGN KEY (building) REFERENCES Classroom(building),
FOREIGN KEY (room_no) REFERENCES Classroom(room_no)
);

You want just one foreign key instead of two, that references the set of columns that is the primary key in the parent table.
So change this:
FOREIGN KEY (building) REFERENCES Classroom(building),
FOREIGN KEY (room_no) REFERENCES Classroom(room_no)
To:
FOREIGN KEY (building, roo_no) REFERENCES Classroom(building, roo_no)
It is important to note that:
the datatypes (and length, or precision) of the columns must be identical
the columns in the foreign key must appear in the same order as in the primary key
Unrelated: year is a language keyword in MySQL, hence not a good choice for a column name.

Related

Failed to add the foreign key

I am trying to create two tables
CREATE TABLE Submissions
(
quiz_ID INT(2) UNSIGNED,
quiz_duration TIME,
student_ID INT(2) UNSIGNED,
attempt_date date,
PRIMARY KEY (quiz_ID, student_ID)
);
and
CREATE TABLE Students
(
student_ID INT(2) UNSIGNED,
student_name VARCHAR(100),
PRIMARY KEY (student_ID),
FOREIGN KEY (student_ID) REFERENCES Submissions(student_ID)
);
However, when I try to create the second table, it gives me an error
ERROR 1822 (HY000): Failed to add the foreign key constraint. Missing index for constraint 'students_ibfk_1' in the referenced table 'Submissions'
How do I fix it?
A foreign key must reference a primary key. You have defined the primary key of SUBMISSIONS as a compound key of (quiz_ID, student_ID). Consequently this does not match the foreign key reference of STUDENTS, where you attempt to reference a single column Submissions(student_ID). That's why you get the error.
But let's drill down into this. You tagged your question [database-design], and that was a good call because this issue arises from your data model.
A student can (presumably) participate in more than one quiz and therefore have more than one submission. This indicates that your data model is wrong. Whenever we have a 1:M relationship the 1 end (in this case STUDENTS) is referenced by a foreign key on the M end (i.e. SUBMISSIONS).
It also seems likely that your data model is missing a table for QUIZZES, and SUBMISSIONS should in fact be an intersection table.
Given all this, your tables should look like this:
CREATE TABLE Quizzes
(
quiz_ID INT(2) UNSIGNED,
quiz_duration TIME
PRIMARY KEY (quiz_ID)
);
CREATE TABLE Students
(
student_ID INT(2) UNSIGNED,
student_name VARCHAR(100),
PRIMARY KEY (student_ID)
);
CREATE TABLE Submissions
(
quiz_ID INT(2) UNSIGNED,
student_ID INT(2) UNSIGNED,
attempt_date date,
PRIMARY KEY (quiz_ID, student_ID),
FOREIGN KEY (quiz_ID) REFERENCES Quizzes(quiz_ID),
FOREIGN KEY (student_ID) REFERENCES Students(student_ID)
);
You have the foreign keys in the wrong order. The submissions should have the foreign key constraint. So:
CREATE TABLE Submissions (
quiz_ID INT(2) UNSIGNED,
quiz_duration TIME,
student_ID INT(2) UNSIGNED,
attempt_date date,
PRIMARY KEY (quiz_ID, student_ID),
CONSTRAINT fk_subsmissions_student_id FOREIGN KEY (student_id) REFERENCES students(student_id)
);
Of course, the Students table needs to be created, before the foreign key is defined.

SQL Error, unable to create table on a certain format

I am facing an error when creating a table between the following two statement
CREATE TABLE SECTION (
cid varchar(10) not null,
sno varchar(3) not null,
primary key (cid, sno),
foreign key (cid) references COURSE (cid)
);
CREATE TABLE ROUND_RELEASE (
cid varchar(10) not null,
sno varchar(3) not null,
rid int not null,
foreign key (cid) references SECTION (cid),
foreign key (sno) references SECTION (sno),
foreign key (rid) references ROUND (rid)
);
Error Code: 1822. Failed to add the foreign key constraint. Missing index for constraint 'round_release_ibfk_2' in the referenced table 'section'
However, when I try to swap the primary key order in SECTION table, I am able to create both table without error
CREATE TABLE SECTION (
cid varchar(10) not null,
sno varchar(3) not null,
primary key (**sno, cid**),
foreign key (cid) references COURSE (cid)
);
CREATE TABLE ROUND_RELEASE (
cid varchar(10) not null,
sno varchar(3) not null,
rid int not null,
foreign key (cid) references SECTION (cid),
foreign key (sno) references SECTION (sno),
foreign key (rid) references ROUND (rid)
);
The follow code above works, and I only swap the attribute, from my knowledge, the order does not matter, thus I am quite puzzled by why is this occurring.
Any guidance on this? Thanks!
Based on the error message, I assume that you are using MySQL.
What you are seeing is a documented behavior:
In the referenced table, there must be an index where the referenced columns are the first columns in the same order.
Let me pinpoint, however, that your code probably does not do what you really want. You probably should be creating a compound foreign key, that references the tuples of columns, rather than one foreign key per column:
create table round_release (
cid varchar(10) not null,
sno varchar(3) not null,
rid int not null,
foreign key (cid, sno) references section(cid, sno),
foreign key (rid) references round(rid)
);
One last thing to note is that your round_release table has no primary key defined; this is not a good practice, and might hurt you in several ways in the future. So, do create a primary key for the table, either as a separate column (possibly auto-incremented), or as a combination of existing columns.

Trouble with SQL 1005 errors (errno 150)

I, like many others, am struggling with the infamous errno 150 in mySQL. I know it has to do with foreign keys, and I know there are already many questions about this issue, but after spending a substantial amount of time searching for a solution I am yet to find one that fits my specific case. Almost every error has been worked out of this travel database, but this final one arises upon trying to create a table entitled leg. I will post below the tables that are involved with this.
CREATE TABLE ticket(
id int UNSIGNED NOT NULL,
passenger_id int UNSIGNED,
trip_id int UNSIGNED,
leg_no int UNSIGNED,
purchased_on datetime,
reservation_date date,
PRIMARY KEY(id),
CONSTRAINT fk_ticket_passenger_id_passenger FOREIGN KEY
(passenger_id) REFERENCES passenger(id),
CONSTRAINT fk_ticket_trip_id_trip FOREIGN KEY
(trip_id) REFERENCES trip(id),
CONSTRAINT fk_ticket_leg_no_leg FOREIGN KEY
(leg_no) REFERENCES leg(leg_no));
CREATE TABLE trip(
id int UNSIGNED NOT NULL,
number_of_legs int UNSIGNED,
PRIMARY KEY(id));
CREATE TABLE leg(
trip_id int UNSIGNED NOT NULL,
leg_no int UNSIGNED NOT NULL,
origin_id int UNSIGNED,
destination_id int UNSIGNED,
depart_time time,
arrive_time time,
vdesignation varchar(255),
price decimal(13,2),
PRIMARY KEY(trip_id, leg_no),
CONSTRAINT fk_leg_trip_id_trip FOREIGN KEY
(trip_id) REFERENCES trip(id),
CONSTRAINT fk_leg_vdesignation_vehicle FOREIGN KEY
(vdesignation) REFERENCES vehicle(designation),
CONSTRAINT fk_leg_origin_id_island FOREIGN KEY
(origin_id) REFERENCES island(id),
CONSTRAINT fk_leg_destination_id_island FOREIGN KEY
(destination_id) REFERENCES island(id));
CREATE TABLE vehicle(
designation varchar(255) NOT NULL,
vtype varchar(255),
capacity int UNSIGNED,
PRIMARY KEY(designation));
CREATE TABLE island(
id int UNSIGNED NOT NULL,
iname varchar(255),
can_fly tinyint UNSIGNED,
PRIMARY KEY(id));
I am aware that this question gets asked a lot, and I'm sure it gets old, I will be incredibly appreciative of any advice that you may have for me. I've searched quite thoroughly for the solution and cannot seem to figure it out. Thanks ahead of time for any info you can give me!
EDIT: Here is the specific warning info for the error:
*************************** 1. row ***************************
Level: Error
Code: 1005
Message: Can't create table 'travel.leg' (errno: 150)
1 row in set (0.04 sec)
EDIT 2: Added the vehicle table in response to the first answer, because somehow I forgot to add it in the first place.
I see two potential problems with the foreign keys in your leg table:
1. The first problem is with the fk_leg_vdesignation foreign key
CONSTRAINT fk_leg_vdesignation_vehicle FOREIGN KEY (vdesignation)
REFERENCES vehicle(designation)
You never showed us the vehicle table, so we can't verify that the designation column there as the same type as leg.vdesignation, which is varchar(255). If the types don't match, or if vehicle.designation does not exist, you should get the 150 error you are seeing.
2. The following two foreign keys in leg both appear to be referencing the same column in the island table:
CONSTRAINT fk_leg_origin_id_island FOREIGN KEY (origin_id) REFERENCES island(id)
CONSTRAINT fk_leg_destination_id_island FOREIGN KEY (destination_id) REFERENCES island(id)
I don't see the point of having both of them. Furthermore, the type of leg.origin_id and leg.destination_id is int UNSIGNED, while the type of the foreign column island.id is int UNSIGNED NOT NULL. Since the types are not exactly the same, this could be causing the error 150.
I ended up figuring it out via a sudden burst of intuition. The issue actually came from the ticket table. To resolve the issue, I combined the final two foreign keys of the table. This means that I changed my constraints from this:
CONSTRAINT fk_ticket_trip_id_trip FOREIGN KEY
(trip_id) REFERENCES trip(id),
CONSTRAINT fk_ticket_leg_no_leg FOREIGN KEY
(leg_no) REFERENCES leg(leg_no));
To this:
CONSTRAINT fk_ticket_leg_no_leg FOREIGN KEY
(trip_id, leg_no) REFERENCES leg(trip_id, leg_no));
My understanding of what went wrong is that a foreign key is supposed to reference a primary key of another table. When the second of the two foreign keys referred to leg.leg_no, it was only referring to part of the key. leg.leg_no is a prime attribute from the primary key, but on its own cannot identify a particular row of the table, so it will not function properly as a foreign key reference.
Thank you anyway to Tim for helping me! Without your comment about having two foreign keys refer to the same key, I may never have thought of this.

how to make a primary key a foreign key in another table?

These are my tables. I have a problem with the last one (Inscription) it doesn't accept CodeProjet as a foreign key. The error says table (Projet) doesn't have a primary key called CodeProjet but it does! I have used every trick that I know and nothing. I altered the table to add constraint, etc. Still nothing. I always get the same error. Here are the tables:
create database Gestion_Stages_Employe
create table Employe
(
NumEmploye int primary key,
NomEmploye varchar(15),
PrenomEmploye varchar(15),
SexeEmploye varchar(10),
DNaissEmploye date,
FonctionEmploye varchar(20)
)
create table TypeProjet
(
TypeProjet varchar(20) primary key,
libelleProjet varchar(20),
DureeProjet date,
)
create table Projet
(
CodeProjet int,
TypeProjet varchar(20),
DateDebut Date,
DateFin Date,
Constraint Pk_CodeProj primary key (CodeProjet,TypeProjet),
Constraint FK_TypeProj foreign key (TypeProjet) references TypeProjet(TypeProjet),
)
create table Inscription
(
NumEmploye int foreign key references Employe(NumEmploye),
CodeProjet int foreign key references Projet(CodeProjet),
dateiscription Date,
primary key (NumEmploye,CodeProjet),
)
As was mentioned in the comment, the Primary Key on the Projet table is a "composite key" (multiple columns are required to enforce uniqueness).
As a result, for your foreign key to work, you need to either remove "TypeProjet" from the primary key of Project (assuming CodeProjet is sufficient to uniquely identify a Projet), or you need to add TypeProjet to the Inscription table and define your foreign key with both columns, for example:
create table Inscription (
NumEmploye int foreign key references Employe(NumEmploye),
CodeProjet int,
dateiscription Date,
TypeProjet varchar(20),
Constraint fk_Inscription_project Foreign key (CodeProjet,TypeProjet) references Projet(CodeProjet,TypeProjet),
primary key (NumEmploye,CodeProjet),
)

SQL error - There are no primary or candidate keys in the referenced table

Firstly I created a CourseSections table like below:
Create Table CourseSections(
CourseNo Integer NOT NULL CHECK(CourseNo BETWEEN 100 AND 999),
SectionNo Integer NOT NULL,
InstructorNo Integer NOT NULL,
Year Integer NOT NULL,
Semester Integer NOT NULL,
FOREIGN KEY(CourseNo) REFERENCES Courses(CourseNo),
PRIMARY KEY(SectionNo, Year, Semester)
);
Then I created another table that has foreign keys referencing to table CourseSections keys:
Create Table Enrollments(
CourseNo Integer NOT NULL CHECK(CourseNo BETWEEN 100 AND 999),
Semester Integer NOT NULL,
Year Integer NOT NULL,
SectionNo Integer NOT NULL,
FOREIGN KEY(CourseNo) REFERENCES Courses(CourseNo),
FOREIGN KEY(Year) REFERENCES CourseSections(Year),
FOREIGN KEY(Semester) REFERENCES CourseSections(Semester),
FOREIGN KEY(SectionNo) REFERENCES CourseSections(SectionNo)
);
Then I'm getting an error message saying
There are no primary or candidate keys in the referenced table 'CourseSections'
that match the referencing column list in the foreign key
FK__Enrollment__Year__3890146B'.
The rest foreign keys are all fine except the ones referencing to the table CourseSections. Can anyone tell me where the problem is? Very much appreciated!!
FOREIGN KEY(SectionNo) REFERENCES CourseSections(SectionNo)
should work, but the other foreign keys will not since they don't really have an index; they are lower parts of a composite index. A composite index is used for columns only in order of how it was created. You would either needs to make unique indexes on CourseSections.Year and CourseSections.Semester, or, more likely, create a single composite foreign key like this:
FOREIGN KEY(SectionNo, Year, Semester) REFERENCES CourseSections(SectionNo, Year, Semester)