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?
Related
I'm trying to make a many-to-many relationship between two tables In Mysql WorkBench, and one of those 2 tables has a composite primary key ( parts are coming from 2 foreign keys). When I'm trying to generate the SQL I'm getting this error :
ERROR: Error 1215: Cannot add foreign key constraint
SQL Code:
-- -----------------------------------------------------
-- Table `A_D_schema`.`Resources_has_OwnerGroups`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `A_D_schema`.`Resources_has_OwnerGroups` (
`Resources_id` INT NOT NULL,
`OwnerGroups_id` INT NOT NULL,
`OwnerGroups_Instances_has_Customers_Instances_idInstances` INT NOT NULL,
`OwnerGroups_Instances_has_Customers_Customers_idCustomers` INT NOT NULL,
PRIMARY KEY (`Resources_id`, `OwnerGroups_id`, `OwnerGroups_Instances_has_Customers_Instances_idInstances`, `OwnerGroups_Instances_has_Customers_Customers_idCustomers`),
INDEX `fk_Resources_has_OwnerGroups_OwnerGroups1_idx` (`OwnerGroups_id` ASC, `OwnerGroups_Instances_has_Customers_Instances_idInstances` ASC, `OwnerGroups_Instances_has_Customers_Customers_idCustomers` ASC),
INDEX `fk_Resources_has_OwnerGroups_Resources1_idx` (`Resources_id` ASC),
CONSTRAINT `fk_Resources_has_OwnerGroups_Resources1`
FOREIGN KEY (`Resources_id`)
REFERENCES `A_D_schema`.`Resources` (`id`)
ON DELETE NO ACTION
ON UPDATE NO ACTION,
CONSTRAINT `fk_Resources_has_OwnerGroups_OwnerGroups1`
FOREIGN KEY (`OwnerGroups_id` , `OwnerGroups_Instances_has_Customers_Instances_idInstances` , `OwnerGroups_Instances_has_Customers_Customers_idCustomers`)
REFERENCES `A_D_schema`.`OwnerGroups` (`id` , `Instances_has_Customers_Instances_idInstances` , `Instances_has_Customers_Customers_idCustomers`)
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB
From the SHOW ENGINE INNODB STATUS I can see this message :
Cannot resolve column name close to:
)
ON DELETE NO ACTION
ON UPDATE NO ACTION,
CONSTRAINT `fk_Resources_has_OwnerGroups_OwnerGroups1`
FOREIGN KEY (`OwnerGroups_id` , `OwnerGroups_Instances_has_Customers_Instances_idInstances` , `OwnerGroups_Instances_has_Customers_Customers_idCustomers`)
REFERENCES `A_D_schema`.`OwnerGroups` (`id` , `Instances_has_Customers_Instances_idInstances` , `Instances_has_Customers_Customers_idCustomers`)
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB
The SHOW CREATE TABLE Resources and SHOW CREATE TABLE OwnerGroups :
CREATE TABLE `Resources` (
`idResources` int(11) NOT NULL AUTO_INCREMENT,
`email` varchar(45) DEFAULT NULL,
`role` int(11) DEFAULT NULL COMMENT 'role : 1 disptcher \n0 admin',
PRIMARY KEY (`idResources`),
UNIQUE KEY `idresources_UNIQUE` (`idResources`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
CREATE TABLE `OwnerGroups` (
`idOwnerGroups` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(45) DEFAULT NULL,
`group` int(11) DEFAULT NULL,
PRIMARY KEY (`idOwnerGroups`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
CONSTRAINT `fk_Resources_has_OwnerGroups_Resources1`
FOREIGN KEY (`Resources_id`)
REFERENCES `A_D_schema`.`Resources` (`id`)
Your Resources table doesn't have a column id. Its primary key is idResources.
CONSTRAINT `fk_Resources_has_OwnerGroups_OwnerGroups1`
FOREIGN KEY (`OwnerGroups_id` , `OwnerGroups_Instances_has_Customers_Instances_idInstances` , `OwnerGroups_Instances_has_Customers_Customers_idCustomers`)
REFERENCES `A_D_schema`.`OwnerGroups` (`id` , `Instances_has_Customers_Instances_idInstances` , `Instances_has_Customers_Customers_idCustomers`)
Your OwnerGroups table doesn't have a column id. Its primary key is idOwnerGroups. It doesn't have the other two columns you reference at all.
In general, when you declare a foreign key, first you name the columns in the child table:
CREATE TABLE Child (
childCol1 INT,
childCol2 INT,
...
FOREIGN KEY (childCol1, childCol2) ...
Then you reference columns in the parent table:
... REFERENCES Parent (parentCol1, parentCol2)
);
You must use the names of columns as they exist in the parent table.
The columns you reference in the parent table must together be the PRIMARY KEY or UNIQUE KEY of that table. In other words, given the example above, it would not work against this Parent table:
CREATE TABLE Parent (
parentCol1 INT,
parentCol2 INT,
PRIMARY KEY (parentCol1)
);
Because the PRIMARY KEY does not include parentCol2.
In your case, the following should work:
CREATE TABLE IF NOT EXISTS `A_D_schema`.`Resources_has_OwnerGroups` (
`Resources_id` INT NOT NULL,
`OwnerGroups_id` INT NOT NULL,
`OwnerGroups_Instances_has_Customers_Instances_idInstances` INT NOT NULL,
`OwnerGroups_Instances_has_Customers_Customers_idCustomers` INT NOT NULL,
PRIMARY KEY (`Resources_id`, `OwnerGroups_id`, `OwnerGroups_Instances_has_Customers_Instances_idInstances`, `OwnerGroups_Instances_has_Customers_Customers_idCustomers`),
CONSTRAINT `fk_Resources_has_OwnerGroups_Resources1`
FOREIGN KEY (`Resources_id`)
REFERENCES `A_D_schema`.`Resources` (`idResources`)
ON DELETE NO ACTION
ON UPDATE NO ACTION,
CONSTRAINT `fk_Resources_has_OwnerGroups_OwnerGroups1`
FOREIGN KEY (`OwnerGroups_id`)
REFERENCES `A_D_schema`.`OwnerGroups` (`idOwnerGroups`)
ON DELETE NO ACTION
ON UPDATE NO ACTION
) ENGINE = InnoDB
I took out a couple of INDEX definitions that are redundant. You don't need to index your PRIMARY KEY, it's already the clustered index of the table. You don't need to index the column you use in a foreign key declaration, MySQL will index that column automatically if it need to (though if an index already exists for that column, the FK constraint will use that index).
I'm not sure I understand what your other two columns OwnerGroups_Instances_has_Customers_Instances_idInstances and OwnerGroups_Instances_has_Customers_Customers_idCustomers are meant to do. Typically in a many-to-many table, you only need enough columns to reference the primary keys of the respective parent tables.
Re your comment:
You should try refreshing the view of the schema from time to time. There's a button with a pair of curvy arrows, to the right of "SCHEMAS".
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
I have a table which is using to map two primary keys of other two tables. i make these two fields as foreign keys. The mapping table has no primary key When i am trying to insert 2 value which already in that two tables, i am getting Cannot add or update a child row: a foreign key constraint fails error.
How can i solve this issue ?
My Table is like this :
CREATE TABLE IF NOT EXISTS fuse_package_component_members
( component_id int(11) NOT NULL,
member_type int(11) NOT NULL,
member_id int(11) NOT NULL,
active_date date NOT NULL,
inactive_date date NOT NULL,
KEY component_id (component_id),
KEY member_id (member_id) )
ENGINE=InnoDB DEFAULT CHARSET=latin1
ALTER TABLE fuse_package_component_members
ADD CONSTRAINT comp_id_fk
FOREIGN KEY (component_id) REFERENCES fuse_component_definition (component_id) ON UPDATE NO ACTION,
ADD CONSTRAINT ele_id_fk
FOREIGN KEY (member_id) REFERENCES fuse_product_element (element_id)
ON DELETE NO ACTION ON UPDATE NO ACTION;
SET foreign_key_checks = 0;
UPDATE ...
SET foreign_key_checks = 1;
https://dev.mysql.com/doc/refman/5.5/en/create-table-foreign-keys.html
Remove the foreign key constraint from the table, insert the data and re-enforce the constraint..
ALTER TABLE table_name
DROP FOREIGN KEY constraint_name
if you want to check the constraint name, just run the query
show create table table_name
It will show you the whole schema along with all the imposed constraints...
Add the constraints again
A good link to follow -> http://www.w3schools.com/sql/sql_foreignkey.asp
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;
^