Trouble with SQL 1005 errors (errno 150) - mysql

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.

Related

MYSQL - Cannot add foreign key constraint, but why?

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.

MySQL - Error: 150 "Foreign key constraint is incorrectly formed")

Got an odd problem I cant solve after browsing dozens of forum posts, and my local SQL Books.
I've got two tables, and want to add a foreign key to one of them. The foreign key and primary key share the same datatype and charset and yet I cannot add the Foreign Key at all.
addon_account
name
type
comments
id
int(11)
Primary Key
name
varchar(60)
Primary Key
label
varchar(255)
shared
int(11)
addon_account_data
name
type
comments
id
int(11)
Primary Key
account_name
varchar(60)
Primary Key
money
double
owner
varchar()
The query I ran:
ALTER TABLE `addon_account_data` ADD FOREIGN KEY (`account_name`) REFERENCES `addon_account`(`name`) ON DELETE RESTRICT ON UPDATE RESTRICT;
Can't get it to work. Tosses out the same issue the entire time.
You are creating a foreign key on addon_account_data(account_name) that references addon_account(name). You have a composite primary the referred table : addon_account(id, name).
This is not allowed in MySQL, as explained in the documentation:
MySQL requires indexes on foreign keys and referenced keys so that foreign key checks can be fast and not require a table scan. In the referencing table, there must be an index where the foreign key columns are listed as the first columns in the same order.
Possible solutions:
add an additional column in the referring table: addon_account_data(account_id, account_name) and create a composite primary key to the corresponding columns in addon_account
create an index on addon_account(name) (probably the simplest solution)
change the order of the columns in the primary key of the referred table, like: addon_account(name, id) (you might want to first consider the impacts this may have in terms of performance)
I am not exactly a MySQL guy, but:
I believe the problem is that you are referencing only part of the primary key:
Your table addon_account has a composite key PK(id, name).
So, to put your relationship to work, you will need to add 'account_id' as part of the foreign key as well:
ALTER TABLE addon_account_data ADD FOREIGN KEY (account_id, account_name) REFERENCES addon_account(id, name)
This thread deals with something similar.
I hope this helps.
EDITED
I have installed a MySQL server instance on my local machine... (MySQL 8).
I have run the script below, and it worked (giving warnings about integer display being a deprecated feature, so I would recommend ommitting it):
CREATE TABLE addon_account(
id INT(11) NOT NULL,
`name` VARCHAR(60) NOT NULL,
label VARCHAR(255),
shared INT(11),
CONSTRAINT pk_addon_account PRIMARY KEY(id, `name`));
CREATE TABLE addon_account_data (
id INT(11) NOT NULL,
account_name VARCHAR(60) NOT NULL,
account_id INT(11),
money DOUBLE,
`owner` VARCHAR(255),
CONSTRAINT pk_addon_account_data PRIMARY KEY(id, account_name),
CONSTRAINT fk_addon_account_account_data FOREIGN KEY(account_id, account_name)
REFERENCES addon_account(id, `name`));
Could you try it and see if this works for you?
I am not that familiar with MySQL.
make sure that the 2 tables have the same collation
like
COLLATE='utf8_general_ci'

unable to set foreign key mysql

I am developing a patch version which is by create or update existing table by using raw sql.When I ran these 3 queries like below
first query Success
CREATE TABLE ts_overtime_scheme_histories( id int AUTO_INCREMENT NOT NULL,
name VARCHAR(255),
workdays INT,
break_payable VARCHAR(25),
roundable VARCHAR(25),
round_rule VARCHAR(10), round_minute INT,
type enum('ratio','fixed') DEFAULT 'ratio',
overtime_request_id INT UNSIGNED NOT NULL, PRIMARY KEY(id),
FOREIGN KEY(overtime_request_id) REFERENCES ts_overtime_requests(id) );
Second query success
CREATE TABLE ts_overtime_scheme_details_histories( id INT AUTO_INCREMENT NOT NULL,
hour FLOAT,
ratio FLOAT,
overtime_scheme_history_id INT(11) UNSIGNED NOT NULL,
PRIMARY KEY(id));
And now I am trying to connect second table to the first table. So the first table has foreign key on the second table. So I ran the third query
ALTER TABLE ts_overtime_scheme_details_histories ADD FOREIGN KEY (`overtime_scheme_history_id`) REFERENCES `ts_overtime_scheme_histories` (`id`) ON DELETE CASCADE;
But somehow it failed. The error report is below
General error: 1005 Can't create table `db_test`.`#sql-ea4_28` (errno: 150 "Foreign key constraint is incorrectly formed") (SQL: ALTER TABLE ts_overtime_scheme_details_histories
ADD FOREIGN KEY (`overtime_scheme_history_id`) REFERENCES `ts_overtime_scheme_histories` (`id`)
ON DELETE CASCADE;)
Can somebody help me to find what I miss? At first, I suspect the primary and foreign key data length is not similar, but when I double checked, it is correct.
Edit:
table ts_overtime_requests was created using laravel framework.
Column datatype of the foreign key column must match exactly the datatype of referenced key column.
In this case, the reported behavior (Error 1005) is expected because there's a difference in the datatypes of the two columns.
One of the columns is signed integer, the other column is UNSIGNED integer.
Quick fix would be to change the datatype of overtime_scheme_history_id so that is is signed. (Remove the UNSIGNED keyword.)

MySQL Error Code 1215: Cannot add foreign key Constraint

I'm very new to SQL, I'm trying to define a 2 tables Hospital and Hospital_Address but when I'm trying to add foreign key in Hospital_Address it throws an error: "1215: Cannot add foreign key"
create table Hospital (
HId Int not null,
HName varchar(40) not null,
HDept int, Hbed Int,
HAreaCd int not null,
Primary Key (HId)
);
create table Hospital_Address (
HAreaCd Int not null,
HArea varchar(40) not null,
HCity varchar(40),
HAdd1 varchar(40),
HAdd2 varchar(40),
Primary Key (HArea),
foreign key (HAreaCd) references Hospital (HAreaCd));
Please help me in this regard. Thanks in advance.
MySQL requires that there be an index on the HAreaCd column in the parent Hospital table, in order for you to reference that column in a FOREIGN KEY constraint.
The normative pattern is for the FOREIGN KEY to reference the PRIMARY KEY of the parent table, although MySQL extends that to allow a FOREIGN KEY to reference a column that is a UNIQUE KEY, and InnoDB extends that (beyond the SQL standard) and allows a FOREIGN KEY to reference any set of columns, as long as there is an index with those columns as the leading columns (in the same order specified in the foreign key constraint.) (That is, in InnoDB, the referenced columns do not need to be unique, though the behavior with this type of relationship may not be what you intend.)
If you create an index on that column in Hospital table, e.g.:
CREATE INDEX Hospital_IX1 ON Hospital (HAreaCd);
Then you can create a foreign key constraint that references that column.
However, because this is a non-standard extension of MySQL and InnoDB, the "best practice" (as other answers here indicate) is for a FOREIGN KEY to reference the PRIMARY KEY of the foreign table. And ideally, this will be a single column.
Given the existing definition of the Hospital table, a better option for a foreign key referencing it would be to add the Hid column to the Hospital_Address table
... ADD HId Int COMMENT 'FK ref Hospital.HId'
... ADD CONSTRAINT FK_Hospital_Address_Hospital
FOREIGN KEY (HId) REFERENCES Hospital (HId)
To establish the relationship between the rows, the values of the new HId column will need to be populated.
You cannot add a foreign key to a non-primary key element of another table usually.
If you really need to do so, refer to this question for help : Foreign Key to non-primary key
HAreaCd in the Hospital table should be a primary key. Only then can you reference it in the Hospital_Address table

MYSQL Error # 1005

I have been trying to create a foregin key with nbrseats but I i get the error 1005 all the time.
CAn someone help me!?
create table theater (
name varchar(30) primary key,
nbrseats int not null
) ENGINE=INNODB;
create table reservation (
nbr integer auto_increment,
users_username varchar(30),
cinemashow_showdate date,
movies varchar(30),
nbrseats int not null,
primary key (nbr),
foreign key (nbrseats) references theater(nbrseats),
foreign key (users_username) REFERENCES users(username)
on delete cascade,
foreign key (cinemashow_showdate, movies) references cinemashow(showdate, movie_title)
on delete cascade
) ENGINE=INNODB;
In order to be a FOREIGN KEY in another table, you must have an index created on theater.nbrseats. And in order to be able to reference a specific row reliably, it should therefore be a UNIQUE index. Otherwise, if you have duplicate values, the referencing table won't be able to discern which row it references. Even though InnoDB will allow you to create the relationship on a non-unique index, it is likely not the behavior you are looking for.
See this question for more info on that bit.
create table theater (
name varchar(30) primary key,
nbrseats int not null,
UNIQUE INDEX `idx_nbrseats` (nbrseats)
) ENGINE=INNODB;
The same will be true of the other FOREIGN KEY definitions in your table reservation, though we do not see their referenced tables posted here. The rules are:
The referenced column must be indexed (independently of any other compound indexes on it)
The referencing column must have exactly the same data type.
This kind of calls into question your design, however. If you are attaching a number of seats to a reservation, will the reservation number of seats exactly match the number available in the theater? Also this means that you could not have 2 theaters with the same number of seats.
You may need to reconsider your design here, and perhaps create a FOREIGN KEY that references theater.name instead of theater.nbrseats.