I have an error code which is Error Code: 1215. Cannot add foreign key constraint in MySQL. My code is
DROP TABLE IF EXISTS Formed;
DROP TABLE IF EXISTS Album;
DROP TABLE IF EXISTS Band;
DROP TABLE IF EXISTS Customers;
DROP TABLE IF EXISTS Track;
CREATE TABLE Formed(
FormedID int NOT NULL,
YearFormed int,
CountryFormed varchar(50),
CityFormed varchar(50),
BandMembers varchar(400),
PRIMARY KEY(FormedID))
ENGINE=InnoDB;
CREATE TABLE Track (
TrackID int NOT NULL,
AlbumID int NOT NULL,
Songs varchar (100),
TrackNumber varchar (20),
Title varchar (20),
TrackDuration varchar (4),
PRIMARY KEY (TrackID),
FOREIGN KEY (AlbumID) REFERENCES Album(AlbumID)ON DELETE SET NULL ON UPDATE CASCADE)
ENGINE=InnoDB;
CREATE TABLE Album(
AlbumID int NOT NULL,
TrackID int NOT NULL,
BandID int NOT NULL,
Price varchar(5),
PublicationDate varchar(11),
Title varchar(30),
Genre varchar (36),
PRIMARY KEY(AlbumID),
FOREIGN KEY (TrackID) REFERENCES Track(TrackID)ON DELETE SET NULL ON UPDATE CASCADE,
FOREIGN KEY (BandID) REFERENCES Band(BandID)ON DELETE SET NULL ON UPDATE CASCADE)
ENGINE=InnoDB;
CREATE TABLE Band(
BandID int NOT NULL,
AlbumID int NOT NULL,
RecordLabel varchar(50),
PRIMARY KEY(BandID),
FOREIGN KEY (AlbumID) REFERENCES Album(AlbumID)ON DELETE SET NULL ON UPDATE CASCADE)
ENGINE=InnoDB;
CREATE TABLE Customers (
CustomerID int NOT NULL,
CName varchar (20),
CPhone int (11),
CEmail varchar (50),
CPPaid varchar (50),
CPDate date,
PRIMARY KEY (CustomerID))
ENGINE=InnoDB;
It creates the first table named Formed, but it's giving me the error when it tries and creates the second table and I don't know why. I know a bit about MySQL and I'm teaching myself about Foreign Keys. I have had a look online on why I could be getting this error but couldn't find anything useful.
From the error message, it seems like you are trying to create Track table before Album table and hence, it's failing as it is not able to find parent table (and column) for foreign key constraint.
I would suggest creating the tables with Primary keys only and then, apply foreign key constraints once all 3 tables are created, e.g.:
ALTER TABLE `Track`
ADD FOREIGN KEY (AlbumID) REFERENCES Album(AlbumID)ON DELETE SET NULL ON UPDATE CASCADE);
As a rule All reference fields in child tables MUST HAVE index defined on them as like in parent table. They must also follow some other constraints.
As per documentation on foreign key constraints:
REFERENCES parent_tbl_name (index_col_name,...)
Define an INDEX on relevant child columns. And make sure that child column definitions must match with those of their parent column definitions.
Code change suggested:
CREATE TABLE Formed( ... ) -- no change suggested
CREATE TABLE Customers ( ... ) -- no change suggested
CREATE TABLE Band(
...
AlbumID int NOT NULL,
...
KEY (AlbumID), -- <---- add this line
...
);
CREATE TABLE Album(
...
TrackID int NOT NULL,
BandID int NOT NULL,
...
KEY (TrakID), -- <---- add this line
KEY (BandID), -- <---- add this line
...
-- FOREIGN KEY (TrackID) -- <-- add this using ALTER
-- REFERENCES Track(TrackID) -- after creating
-- ON DELETE SET NULL ON UPDATE CASCADE, -- Track table
);
ALTER TABLE Band ADD
FOREIGN KEY ( AlbumID )
REFERENCES Album( AlbumID )
ON DELETE SET NULL ON UPDATE CASCADE;
CREATE TABLE Track ( ... ) -- no changes suggested
ALTER TABLE Album ADD
FOREIGN KEY ( TrackID )
REFERENCES Track( TrackID );
ON DELETE SET NULL ON UPDATE CASCADE;
Refer to:
MySQL Using FOREIGN KEY Constraints
[CONSTRAINT [symbol]] FOREIGN KEY
[index_name] (index_col_name, ...)
REFERENCES tbl_name (index_col_name,...)
[ON DELETE reference_option]
[ON UPDATE reference_option]
reference_option:
RESTRICT | CASCADE | SET NULL | NO ACTION
Related
create database priceTag;
use priceTag;
CREATE TABLE `ProductNumber` (
`Sku` INT auto_increment not null,
`Model` VARCHAR(100),
PRIMARY KEY (`Sku`)
);
ALTER TABLE ProductNumber AUTO_INCREMENT=60000;
CREATE TABLE `Manufacture` (
`Manufacture` VARCHAR(100),
`Model` VARCHAR(100),
`Category` VARCHAR(100),
PRIMARY KEY (`Model`)
);
CREATE TABLE `OpenBox` (
`Condtion` VARCHAR(100),
`LP` INT auto_increment not null,
`MissingItems` VARCHAR(100),
`Model_` VARCHAR(100),
FOREIGN KEY (`Model_`) REFERENCES `Manufacture`(`Model`),
PRIMARY KEY (`LP`)
);
ALTER TABLE OpenBox AUTO_INCREMENT=200000000;
CREATE TABLE `TAG` (
`SKU*` INT,
`Model*` VARCHAR(100),
`PRICE*` DECIMAL(10,2),
`LP*` INT,
`condtion*` VARCHAR(100),
FOREIGN KEY (`SKU*`) REFERENCES `ProductNumber`(`Sku`),
FOREIGN KEY (`Model*`) REFERENCES `Manufacture`(`Model`),
FOREIGN KEY (`LP*`) REFERENCES `OpenBox`(`LP`),
FOREIGN KEY (`condtion*`) REFERENCES `OpenBox`(`condtion`)
);
CREATE TABLE `Inventory` (
`INV` int,
`Sku!` int,
`Model!` VARCHAR(100),
FOREIGN KEY (`Sku!`) REFERENCES `ProductNumber`(`Sku`),
FOREIGN KEY (`Model!`) REFERENCES `Manufacture`(`Model`)
);
The column which you refer on in FOREIGN KEY (`condtion*`) REFERENCES `OpenBox`(`condtion`) (i.e. OpenBox.condtion) is not indexed.
Add needed unique index creation then create TAG table.
DEMO
I tested your code, and then ran SHOW ENGINE INNODB STATUS to get more detailed information about the error.
LATEST FOREIGN KEY ERROR
2021-12-02 09:47:16 0x700007565000 Error in foreign key constraint of table test2/tag:
FOREIGN KEY (condtion*) REFERENCES OpenBox(condtion)
):
Cannot find an index in the referenced table where the
referenced columns appear as the first columns, or column types
in the table and the referenced table do not match for constraint.
It's complaining about this foreign key:
FOREIGN KEY (`condtion*`) REFERENCES `OpenBox`(`condtion`)
The OpenBox.condtion column is not a primary key or unique key. Foreign keys must reference a key of the parent table.
You already have another foreign key in your TAGS table referencing the OpenBox table. Are you intending that the condtion column of the respective row be copied to the TAGS table? That's not how foreign keys are intended to be used.
I want to create a foreign key from 1 table, but only if it does not exist.
Tables are created like that:
CREATE TABLE
IF NOT EXISTS PEs (
id INT(20) AUTO_INCREMENT PRIMARY KEY,
Name varchar(20),
Message varchar(30),
CoordsX double(9,6) SIGNED,
CoordsY double(9,6) SIGNED,
CoordsZ double(9,6) SIGNED,
Status smallint(1) DEFAULT 1,
world varchar(20)
) ENGINE = InnoDB;
CREATE TABLE
IF NOT EXISTS`rh_pe`.`attributes` (
`toid` INT(20) NOT NULL,
`Kommentar` VARCHAR(60) NOT NULL,
`Aktion` varchar(10) NOT NULL,
`Person1` INT NOT NULL,
`Person2` INT
) ENGINE = InnoDB;
The Foreign key should be like so:
ALTER TABLE `attributes`
ADD CONSTRAINT `Const`
FOREIGN KEY (`toid`) REFERENCES `pes`(`id`)
ON DELETE RESTRICT
ON UPDATE RESTRICT;
To create the foreign key, I tried the following two options:
IF NOT EXISTS(
ALTER TABLE `attributes`
ADD CONSTRAINT `Const`
FOREIGN KEY (`toid`) REFERENCES `pes`(`id`)
ON DELETE RESTRICT
ON UPDATE RESTRICT
);
and
ALTER TABLE `attributes`
ADD CONSTRAINT `Const`
FOREIGN KEY
IF NOT EXISTS (`toid`) REFERENCES `pes`(`id`)
ON DELETE RESTRICT
ON UPDATE RESTRICT
But none of them work.
Any Ideas on how I could create the constraint only if it does not exist?
Both of your table examples have the same name, so I suposed that your second table name is "pes" as you mention in your constraint examples. This one should work:
IF NOT EXISTS (SELECT * FROM sys.objects o WHERE o.object_id = object_id(N'`rh_pe`.`Const`') AND OBJECTPROPERTY(o.object_id, N'IsForeignKey') = 1)
BEGIN
ALTER TABLE `rh_pe`.`attributes` ADD CONSTRAINT `Const` FOREIGN KEY (`toid`) REFERENCES `rh_pe`.`pes`(`id`) ON DELETE RESTRICT ON UPDATE RESTRICT;
END
I haven't used the "if (not) exists" clausule for this but you can find a similar question here: If Foreign Key Not Exist Then Add Foreign Key Constraint(Or Drop a Foreign Key Constraint If Exist) without using Name?
I have trouble in adding a foreign key. I have the following script:
CREATE DATABASE IF NOT EXISTS dbdemo;
use dbdemo;
CREATE TABLE categories(
cat_id int unsigned not null auto_increment primary key,
cat_name varchar(255) not null,
cat_description text
) ENGINE=InnoDB;
CREATE TABLE products(
prd_id int unsigned not null auto_increment primary key,
prd_name varchar(355) not null,
prd_price decimal,
cat_id int unsigned not null,
constraint fk_cat
FOREIGN KEY fk_cat( cat_id )
REFERENCES categories( cat_id )
ON UPDATE cascade
ON DELETE RESTRICT
) ENGINE=InnoDB;
CREATE TABLE vendors(
vdr_id int unsigned not null auto_increment primary key,
vdr_name varchar(255)
) ENGINE=InnoDB;
ALTER TABLE products
ADD COLUMN prod_vdr_id int unsigned not null;
Then I got error when I try to add a FOREIGN KEY :
ALTER TABLE products
ADD FOREIGN KEY fk_vendor(prod_vdr_id)
REFERENCES vendor(vdr_id)
ON UPDATE CASCADE
ON DELETE NO ACTION;
Then I got this error:
Error Code: 1005. Can't create table 'dbdemo.#sql-565_35' (errno: 150)
If i run "Show Engine innodb status;" I got :
------------------------
LATEST FOREIGN KEY ERROR
------------------------
150430 15:30:00 Error in foreign key constraint of table dbdemo/#sql-565_35:
FOREIGN KEY fk_vendor(prod_vdr_id)
REFERENCES vendor(vdr_id)
ON UPDATE CASCADE
ON DELETE NO ACTION:
Cannot resolve table name close to:
(vdr_id)
ON UPDATE CASCADE
ON DELETE NO ACTION
Can anyone show me some light where went wrong?
TQVM
It is VENDORS not VENDOR
ALTER TABLE products
ADD FOREIGN KEY fk_vendor(prod_vdr_id)
REFERENCES vendors(vdr_id)
ON UPDATE CASCADE
ON DELETE NO ACTION;
Here's the basic gist of what I'm trying to do:
create table main(id char(1) primary key);
create table other (
id int primary key auto_increment,
main_id char(1),
key m (main_id),
constraint fk foreign key (main_id) references main(id)
);
insert into main(id) values('a');
insert into other(main_id) values('a');
update main inner join other on other.main_id=main.id
set main.id='b', other.main_id='b'
where main.id='a';
This results in a foreign key constraint failure. Is there any way to accomplish this without dropping the foreign keys (not really an option on my large production database)?
You can do this simply by temporarily setting foreign_key_checks=0 in your session:
set foreign_key_checks=0;
update main inner join other on other.main_id=main.id
set main.id='b', other.main_id='b'
where main.id='a';
Another option is to configure the foreign key with the ON UPDATE CASCADE option so that if the primary key is updated on the parent table it will cascade to the child table:
create table main(id char(1) primary key);
create table other (
id int primary key auto_increment,
main_id char(1),
key m (main_id),
constraint fk foreign key (main_id) references main(id) on update cascade
);
So, this is my input, I'm designing a hospital database and I'm creating a table that will hold the relationships between the patients in the 'patients' table and the rooms in the 'room' table (clever, I know).
here's the statement is used to declare both tables:
create table patient_room
(
pr_id int NOT NULL PRIMARY KEY auto_increment,
patient_id int NOT NULL,
room_id int NOT NULL,
)ENGINE = InnoDB;
create table patients
(
patient_id int primary key not null auto_increment,
fname varchar(30),
lname varchar(30),
suffix enum('I','II','III','IV','JR','SR'),
sex enum('M','F','U','T'),
eye_color enum('BK','BR','BL','GY','GR','HZ','MN','DX','UN'),
hair_color enum('BK','BR','BN','RD','WH','SN','BD','UN'),
date_of_birth date not null,
height int unsigned not null,
weight int unsigned not null,
admitted datetime not null
) Engine = InnoDB;
here's my alter statement
alter table patient_room add foreign key (patient_id) references patient(patient_id) on delete cascade on update cascade;
I get the return:
ERROR 1005 (HY000): Can't create table 'Mthomas.#sql-3dac_5f1' (errno: 150)
I was able to alter the table to create a foreign key using
alter table patient_room add foreign key (room_id) references room(room_id) on delete cascade on update cascade;
without error. I do have have patient_id as a foreign key already on another patient_meds table, and I'm thinking that could be the issue... if so? How do I mitigate it?
your table is called patients and not patient. You need to change
alter table patient_room add foreign key (patient_id) references patient(patient_id) on delete cascade on update cascade;
to
alter table patient_room add foreign key (patient_id) references patients(patient_id) on delete cascade on update cascade;
^