Foreign Key Error 1215 - mysql

Trying to create a foreign key on table Supplier for Supplier_ID referencing table Payment.
CREATE TABLE Payment (
Supplier_ID INT (4) NOT NULL,
Date DATE NOT NULL,
Amount INT (4),
Payment_ID INT (4) NOT NULL,
PRIMARY KEY (Payment_ID, Supplier_ID)
);
Query OK, 0 rows affected (0.10 sec)
CREATE TABLE Supplier (
Supplier_ID INT(4) NOT NULL,
Name VARCHAR(4) NOT NULL,
Country VARCHAR(4) NOT NULL,
Reliability_Score INT(4),
Contact_Info VARCHAR(4),
PRIMARY KEY (Supplier_ID)
FOREIGN KEY (Supplier_ID) REFERENCES Payment(Supplier_ID)
);
ERROR 1215 (HY000): Cannot add foreign key constraint
Please let me know if I can provide additional information, thank you.

A foreign key has to reference a unique column. So the Supplier_ID column needs to be unique.
However, it seems like you might have it backward if I'm understanding your intention correctly. It should probably be a foreign key on supplier_ID in the Payment table referencing the supplier table.

In the context of relational databases, a foreign key is a field (or collection of fields) in one table that uniquely identifies a row of another table. In other words, a foreign key is a column or a combination of columns that is used to establish and enforce a link between the data in two tables.
in your code u have declared primary key as PRIMARY KEY (Payment_ID, Supplier_ID) which is a combination of two columns which is totally fine but while creating foreign key FOREIGN KEY (Supplier_ID) REFERENCES Payment(Supplier_ID) you are referring one column to a combination of two columns which is wrong
read here http://en.wikipedia.org/wiki/Foreign_Key
now your solution:
first create Supplier table
CREATE TABLE Supplier (
Supplier_ID INT(4) NOT NULL,
Name VARCHAR(4) NOT NULL,
Country VARCHAR(4) NOT NULL,
Reliability_Score INT(4),
Contact_Info VARCHAR(4),
PRIMARY KEY (Supplier_ID)
);
now the payment table
CREATE TABLE Payment (
Supplier_ID INT (4) NOT NULL,
Date DATE NOT NULL,
Amount INT (4),
Payment_ID INT (4) NOT NULL,
PRIMARY KEY (Payment_ID, Supplier_ID),
FOREIGN KEY (Supplier_ID) REFERENCES Supplier(Supplier_ID)
);

Related

Failed to add the foreign key constraint in MySQL: error 3780

I am getting the error:
Error Code: 3780. Referencing column 'category' and referenced column 'category_id' in foreign key constraint 'product_ibfk_1' are incompatible.
drop table if exists Provider;
drop table if exists Category;
drop table if exists Product;
create table Provider
(
privider_id serial not null primary key,
login_password varchar(20) not null
constraint passrule3 check(login_password sounds like '[A-Za-z0-9]{6,20}'),
fathersname varchar(20) not null,
name_of_contact_face varchar(10) not null,
surname varchar(15),
e_mail varchar(25) unique
constraint emailrule2 check(e_mail sounds like '[A-Za-z0-9]{10,10})\#gmail.com\s?')
);
create table Category
(
title varchar(20),
category_id serial not null primary key
);
create table Product
(
barecode serial not null primary key,
provider_id bigint not null,
manufacturer varchar(25) not null,
category_id bigint not null,
dimensions varchar(10) not null,
amount int not null,
date_of_registration datetime not null,
#constraint 'provider_for_product'
foreign key (provider_id) references Provider (provider_id) on delete restrict on update cascade,
foreign key (category_id) references Category (category_id) on delete restrict on update cascade
);
The datatypes of the two columns referenced in a foreign key constraint need to match
In MySQL, SERIAL is an alias for BIGINT UNSIGNED AUTO_INCREMENT.
To make a foreign key that references this column, it must be BIGINT UNSIGNED, not a signed BIGINT.
You might like to view a checklist of foreign key mistakes I contributed to: https://stackoverflow.com/a/4673775/20860
I also cover foreign key mistakes in more detail in a chapter of my book, SQL Antipatterns Volume 1: Avoiding the Pitfalls of Database Programming.

How to solve the errno: 150 "Foreign key constraint is incorrectly formed" even though my constraint is correct?

I am trying to create three tables :
Hotel Table
CREATE TABLE Hotels(
HotelID VARCHAR(30) NOT NULL,
Name VARCHAR(30) NOT NULL,
City VARCHAR(30) NOT NULL,
Rating VARCHAR(30) NOT NULL,
Description VARCHAR(500) NOT NULL,
PRIMARY KEY (HotelID)
)
Rooms table
CREATE TABLE Rooms (
HotelID VARCHAR(30) NOT NULL,
Room_Number INT NOT NULL,
Price_Rate INT NOT NULL,
Type VARCHAR(30) NOT NULL,
PRIMARY KEY(HotelID, Room_Number),
FOREIGN KEY(HotelID) REFERENCES hotels(HotelID)
)
BookingInfo Table
CREATE TABLE BookingInfo (
HotelID VARCHAR(30) NOT NULL,
UserID VARCHAR(30) NOT NULL,
Room_Number INT NOT NULL,
Arrival_Date DATE NOT NULL,
Departure_Date DATE NOT NULL,
PRIMARY KEY(UserID, HotelID, Room_Number, Arrival_Date),
FOREIGN KEY(HotelID) REFERENCES hotels(HotelID),
FOREIGN KEY(UserID) REFERENCES users(UserID),
FOREIGN KEY (Room_Number) REFERENCES rooms(Room_Number)
)
But when I try to create the third table I am getting errno: 150 "Foreign key constraint is incorrectly formed".
Moreover, when I delete FOREIGN KEY (Room_Number) REFERENCES rooms(Room_Number) the table gets created successfully. But I don't understand why it is not accepting FOREIGN KEY (Room_Number) REFERENCES rooms(Room_Number).
I have also tried to alter the table and change data type but still didn't get any success. Can anyone please point out my the mistake in this codes.
The primary key of Rooms is two columns: (HotelID, Room_Number).
The foreign key in BookingInfo is one column: (Room_Number).
A foreign key should reference the whole primary key of the referenced table. If that primary key has more than one column, all of the columns must be referenced by the foreign key, and in the same order.
Caveat that is not standard SQL and specific to InnoDB: InnoDB allows a foreign key to reference part of a multi-column key in the referenced table, as long as the column is the leftmost column of that key. But in your case, you are referencing the second from the left column of that key, Room_Number. So it's not allowed. And in my opinion, it's a bad idea anyway to reference part of the key, because it leads to weird data anomalies.
REFERENCES rooms(Room_Number) room_number has to be a key or the first node of a multi column key
'In the referencing table, there must be an index where the foreign key columns are listed as the first columns in the same order.' https://dev.mysql.com/doc/refman/5.6/en/create-table-foreign-keys.html
Thanks a lot for the guidance. This code has worked for me :
CREATE TABLE BookingInfo (
HotelID VARCHAR(30) NOT NULL,
UserID VARCHAR(30) NOT NULL,
Room_Number INT NOT NULL,
Arrival_Date DATE NOT NULL,
Departure_Date DATE NOT NULL,
PRIMARY KEY(UserID, HotelID, Room_Number, Arrival_Date),
FOREIGN KEY(UserID) REFERENCES users(UserID),
FOREIGN KEY(HotelID,Room_Number) REFERENCES rooms(HotelID,Room_Number)
)

Error Code: 1822 when data types are matching, with composite key

Getting an
Error Code: 1822. Failed to add the foreign key constraint. Missing
index for constraint 'subject_ibfk_1' in the referenced table
'enrolment'
when attempting to create the subject table. The problem is, the error does not occur on the previous table student. The data types are the same, and the primary keys are defined.
This error occurs for both the enrolment and grade tables.
create table enrolment(
stud_id char(9) not null,
subj_code char(8) not null,
semester tinyint unsigned not null,
year smallint unsigned not null,
comment text,
primary key (stud_id, subj_code, semester, year)
);
create table grade(
stud_id char(9) not null,
subj_code char(8) not null,
semester tinyint unsigned not null,
year smallint unsigned not null,
grade tinyint unsigned,
primary key (stud_id, subj_code, semester, year)
);
create table student(
stud_id char(9) not null,
stud_name char(30),
stud_phone char(12),
stud_date_of_birth date,
stud_city char(26),
stud_address char(30),
stud_postcode char(4),
primary key (stud_id),
foreign key (stud_id)
references grade(stud_id),
foreign key (stud_id)
references enrolment(stud_id)
);
create table subject(
subj_code char(8) not null,
subj_title char(40),
primary key (subj_code),
foreign key (subj_code)
references enrolment(subj_code),
foreign key (subj_code)
references grade(subj_code)
);
The problem is due to the fact that the foreign key, subj_code, is part of a multi-column primary key (PK) in the referenced table enrolment:
primary key (stud_id, subj_code, semester, year)
where this column (subj_code) is not the leftmost one.
Table student does not have this problem because its foreign key column stud_id is the leftmost column of the PK in the referenced table.
To resolve this you can create a new index for the referened column:
ALTER TABLE enrolment ADD INDEX subj_code_idx (subj_code);
Note: You have to do the same for referenced table grade in the other foreign key.
Demo here
FOREIGN KEY of one table is a PRIMARY key of another table. its a mapping key or column between two table.
First of all: you don't make subject_id as primary key in CLO table.
subject_id is act as a primary key in subject table and foreign key in clo table
ALTER TABLE `clo` DROP PRIMARY KEY, ADD PRIMARY KEY(`clo_id`);
ALTER TABLE `subject` DROP PRIMARY KEY, ADD PRIMARY KEY(`subject_id`);
ALTER TABLE clo ADD FOREIGN KEY (subject_id) REFERENCES subject(subject_id)

Can not Add External Index Constraints

This is the exact error that WAMP returns when I run the child code from an external file called entries.txt
ERROR 1215 (HY000): Can not Add External Index Constraints
I need to be able to connect the parent tables to the child table so that links can be made between the tables easily.
The question states:
Create and populate a third table called entries, again using query scripts.
This table should contain foreign keys to allow sensible links to be
made with the other two tables, together with the dates of each exam.
Parent Tables:
CREATE TABLE IF NOT EXISTS students(
student_id INT UNSIGNED NOT NULL AUTO_INCREMENT,
first_name VARCHAR(20) NOT NULL,
middle_name VARCHAR(20),
last_name VARCHAR(40) NOT NULL,
email VARCHAR(60) NOT NULL,
password CHAR(40) NOT NULL,
reg_date DATETIME NOT NULL,
PRIMARY KEY (student_id),
UNIQUE (email));
CREATE TABLE IF NOT EXISTS subjects(
subject_id INT UNSIGNED NOT NULL AUTO_INCREMENT,
subject_name CHAR(30) NOT NULL,
level_of_entry VARCHAR(10) NOT NULL,
exam_board CHAR(20) NOT NULL,
PRIMARY KEY (subject_id));
Child Table:
CREATE TABLE IF NOT EXISTS entries(
date_of_exam DATETIME NOT NULL,
first_name VARCHAR,
middle_name VARCHAR,
last_name VARCHAR,
subject_name CHAR,
level_of_entry VARCHAR,
exam_board CHAR,
INDEX idx_first_name(first_name),
INDEX idx_middle_name(middle_name),
INDEX idx_last_name(last_name),
INDEX idx_subject_name(subject_name),
INDEX idx_level_of_entry(level_of_entry),
INDEX idx_exam_board(exam_board),
PRIMARY KEY (date_of_exam),
CONSTRAINT fk_first_name FOREIGN KEY (first_name) REFERENCES students(first_name),
CONSTRAINT fk_middle_name FOREIGN KEY (middle_name) REFERENCES students(middle_name),
CONSTRAINT fk_last_name FOREIGN KEY (last_name) REFERENCES students(last_name),
CONSTRAINT fk_subject_name FOREIGN KEY (subject_name) REFERENCES subjects(subject_name),
CONSTRAINT fk_level_of_entry FOREIGN KEY (level_of_entry) REFERENCES subjects(level_of_entry),
CONSTRAINT fk_exam_board FOREIGN KEY (exam_board) REFERENCES subjects(exam_board)
)ENGINE=InnoDB;
A foreign key in the child table must reference the primary key of the parent table only. You don't need to create clones of every attribute column of the parent tables, just the primary key column. If you need to read the other attributes, you'd write a query with a JOIN.
CREATE TABLE IF NOT EXISTS entries(
student_id INT UNSIGNED NOT NULL,
subject_id INT UNSIGNED NOT NULL,
date_of_exam DATETIME NOT NULL,
PRIMARY KEY (student_id, subject_id, date_of_exam),
CONSTRAINT fk_student FOREIGN KEY (student_id) REFERENCES students(student_id),
CONSTRAINT fk_subject FOREIGN KEY (subject_id) REFERENCES subjects(subject_id),
)ENGINE=InnoDB;

MySQL: Creating a table that with a foreign key that references a primary key made up of foreign keys

I have a table of books, which stores book IDs and titles, authors, etc., a table of customers which has customer IDs (PK), customer name, birthday. Then there is a table of transactions, which includes the BookId and the CustomerID as foreign keys. The primary key of this transaction table is the two foreign key columns.
The problem is now I am creating a table of book ratings based on transactions which have occurred (So a customer can't rate a book they don't own, or the same book twice.). This table must contain the bookID, the customerID, and the rating info. I'm trying to constrain the table so that each bookID and customerID row must reference an existing row in the transaction table. However, none of the constraints I've tried so far work. Any help at all would be greatly appreciated.
Here's my tables at the moment:
CREATE TABLE eBook
( BookTitle VARCHAR(50),
BookID CHAR(13) NOT NULL,
BookPub CHAR(4) NOT NULL,
BookDate DATE NOT NULL,
BookHard BOOL NOT NULL,
BookSize INT NOT NULL,
CONSTRAINT PKBookID PRIMARY KEY (BookID)
);
CREATE TABLE customer
( CustID CHAR(9) NOT NULL,
CustSSN CHAR(11) NULL,
CustName VARCHAR(50) NOT NULL,
CustBirth INT(4) NOT NULL,
CONSTRAINT PKCustID PRIMARY KEY (CustID),
CONSTRAINT UniqSSN UNIQUE (CustSSN)
);
CREATE TABLE Buys
( BuysID CHAR(5) NOT NULL
BookID CHAR(13) NOT NULL,
CustID CHAR(9) NOT NULL,
TransDate DATETIME NOT NULL,
Price DECIMAL(5,2) NOT NULL,
CONSTRAINT FK1 FOREIGN KEY (BookID) REFERENCES eBook (BookID)
ON DELETE CASCADE
ON UPDATE CASCADE,
CONSTRAINT FK2 FOREIGN KEY (CustID) REFERENCES customer (CustID)
ON DELETE CASCADE
ON UPDATE CASCADE,
CONSTRAINT PKBuys PRIMARY KEY (BookID, CustID)
);
CREATE TABLE Rating
( BookID CHAR(13) NOT NULL,
CustID CHAR(9) NOT NULL,
RatingID CHAR(5) NOT NULL,
Rating INT(1) NOT NULL,
RatingDate DATE NOT NULL,
CONSTRAINT FK13 FOREIGN KEY (BookID, CustID) REFERENCES buys (BookID, CustID)
ON DELETE CASCADE
ON UPDATE CASCADE,
CONSTRAINT PKRating PRIMARY KEY (RatingID)
);
You already have a foreign key on your Rating table that should constrain Rating rows each to correspond to a Buys row. I suppose that the problem must be with your other objective, that customers cannot rate the same book twice. With respect to that, I guess you have a misconception about foreign keys: they have to be unique on the target table, but they do not automatically have to be unique on the referring side.
To prevent multiple Rating rows having the same combination of BookID and CustomerID, you need an additional UNIQUE constraint on the Rating table, naming those columns. Alternatively, you could give the Rating table a composite primary key consisting of those columns. Either way, you'll have separate constraints, one establishing the uniqueness of those columns in the referring table, and the other constraining them to pairs that appear in the Buys table.
You can create a multi column foreign key reference as documented on http://dev.mysql.com/doc/refman/5.0/en/create-table-foreign-keys.html
That should do the trick.
Your sample code contains an error. You are missing a (,) in the Buys table.
CREATE TABLE eBook
( BookTitle VARCHAR(50),
BookID CHAR(13) NOT NULL,
BookPub CHAR(4) NOT NULL,
BookDate DATE NOT NULL,
BookHard BOOL NOT NULL,
BookSize INT NOT NULL,
CONSTRAINT PKBookID PRIMARY KEY (BookID)
);
CREATE TABLE customer
( CustID CHAR(9) NOT NULL,
CustSSN CHAR(11) NULL,
CustName VARCHAR(50) NOT NULL,
CustBirth INT(4) NOT NULL,
CONSTRAINT PKCustID PRIMARY KEY (CustID),
CONSTRAINT UniqSSN UNIQUE (CustSSN)
);
CREATE TABLE Buys
( BuysID CHAR(5) NOT NULL,
BookID CHAR(13) NOT NULL,
CustID CHAR(9) NOT NULL,
TransDate DATETIME NOT NULL,
Price DECIMAL(5,2) NOT NULL,
CONSTRAINT FK1 FOREIGN KEY (BookID) REFERENCES eBook (BookID)
ON DELETE CASCADE
ON UPDATE CASCADE,
CONSTRAINT FK2 FOREIGN KEY (CustID) REFERENCES customer (CustID)
ON DELETE CASCADE
ON UPDATE CASCADE,
CONSTRAINT PKBuys PRIMARY KEY (BookID, CustID)
);
CREATE TABLE Rating
( BookID CHAR(13) NOT NULL,
CustID CHAR(9) NOT NULL,
Rating INT(1) NOT NULL,
RatingDate DATE NOT NULL,
CONSTRAINT FK13 FOREIGN KEY (BookID, CustID) REFERENCES buys (BookID, CustID)
ON DELETE CASCADE
ON UPDATE CASCADE,
CONSTRAINT PKRating PRIMARY KEY (BookID, CustID)
);
When using this corrected ddl, the tables are created just fine.
I've created some test data
insert into `ebook`(`BookTitle`,`BookID`,`BookPub`,`BookDate`,`BookHard`,`BookSize`) values ('grey','1','ME','2015-02-06',1,10);
insert into `customer`(`CustID`,`CustSSN`,`CustName`,`CustBirth`) values ('1','daCust','Cust',1974);
insert into `buys`(`BuysID`,`BookID`,`CustID`,`TransDate`,`Price`) values ('1','1','1','2015-02-06 00:00:00',10.00);
insert into `rating`(`BookID`,`CustID`,`RatingID`,`Rating`,`RatingDate`) values ('1','1','1',1,'2015-02-06');
Now adding the following data will result in an error due to the foreign key constraint.
insert into `rating`(`BookID`,`CustID`,`RatingID`,`Rating`,`RatingDate`) values ('7','3','1',1,'2015-02-06');
To ensure that the user can add only one rating per book you should add a unique constraint on the fields BookID and CustID or set those fields as primary key. In the working code example above i have added those fields as primary key and removed the obsolete RatingID.