I have two table, with a PK of ID. If say I delete the entry for ID = 1, I want it to automatically delete the FK of ID in the other table. In other words I want so that it should also delete all entries with ID = 1 in the other table. How can I do this? I have linked the PK-FK relationship, but when I delete the entry with ID 1 in the PK table it doesn't delete the FK.
Make sure you're using the InnoDB engine for both tables, and add a foreign-key constraint specifying on delete cascade. Your table creation SQL should look something like this:
create table child_table (
parent_id int references parent_table(id) on delete cascade
) engine 'innodb';
where child_table and parent_table are the names of your child and parent tables.
You have to define your Foreign Key constraints as ON DELETE CASCADE.
Note: You need to use InnoDB storage engine, he default MyISAM storage engine not support foreign keys relation.
CREATE TABLE `table2` (
`id` int(11) NOT NULL auto_increment,
`name` int(11) NOT NULL,
PRIMARY KEY (`id`),
KEY `ids` (`ids`)
CONSTRAINT `foreign` FOREIGN KEY (`ids`)
REFERENCES `table2` (`ids`) ON DELETE CASCADE ON UPDATE CASCADE
)
Related
What is the best approach to delete records from a table which has a foreign key to another table and the other table has a foreign key to it?
For instance, I have the following tables. accounts has one or more networks and accounts must have a single default network.
CREATE TABLE IF NOT EXISTS accounts (
id INT NOT NULL,
networksId INT NOT NULL,
PRIMARY KEY (id),
INDEX fk_accounts_networks1_idx (networksId ASC),
CONSTRAINT fk_accounts_networks1
FOREIGN KEY (networksId)
REFERENCES networks (id)
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB;
CREATE TABLE IF NOT EXISTS networks (
id INT NOT NULL AUTO_INCREMENT,
accountsId INT NOT NULL,
PRIMARY KEY (id),
INDEX fk_sites_accounts1_idx (accountsId ASC),
CONSTRAINT fk_sites_accounts1
FOREIGN KEY (accountsId)
REFERENCES accounts (id)
ON DELETE CASCADE
ON UPDATE NO ACTION)
ENGINE = InnoDB;
Even though I have a CASCADE DELETE on networks FK to accounts, I tried to explicitly delete networks in hopes of getting around the foreign key constraint, however, was not successful.
DELETE a, n FROM accounts a INNER JOIN networks n ON n.accountsId=a.id WHERE a.id=123;
Is my only solution something like the following?
SET FOREIGN_KEY_CHECKS=0;
DELETE FROM networks WHERE accountsId=123;
SET FOREIGN_KEY_CHECKS=1;
DELETE FROM accounts WHERE id=123;
You have a constraint interdependency between both tables. This is not a good design, because it tends to make DDL and DML operations more complicated than normally necessary.
Apart from temporarily disabling a foreign key, the only possible solution to perform a successful DELETE is to make one of the referencing fields nullable so you can break the relation by setting it to NULL before deleting. The ON DELETE CASCADE will take care of dropping the related record in the other table.
Make one the referencing fields nullable :
ALTER TABLE networks MODIFY accountsId INT NULL;
Delete :
UPDATE network SET accountsId = NULL WHERE id = ?;
DELETE FROM network WHERE id = ?;
-- the corresponding record in table accounts gets automatically deleted.
Using Mysql Workbench, I found that the sql of the one_to_one table and one_to_many table is similar. Both use a non-unique foreign key to implement their relationships.
CREATE TABLE IF NOT EXISTS `mydb`.`one_to_one` (
`id` INT NOT NULL,
`parent_id` INT NOT NULL,
PRIMARY KEY (`id`, `parent_id`),
INDEX `fk_one_to_one_parent1_idx` (`parent_id` ASC),
CONSTRAINT `fk_one_to_one_parent1`
FOREIGN KEY (`parent_id`)
REFERENCES `mydb`.`parent` (`id`)
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB
Consequently, I can insert rows in the one_to_one table that reference the same row in the parent table just like the one_to_many table.
Is not this a violation to the one-to-one relationship? Or should I define the one-to-one relationships with a unique foreign key?
Foreign key constraint only checks if a value of parent_id column in table one_to_one exists in parent table or not.
You can handle the issue by adding an unique index for parent_id in one_to_one table.
ALTER TABLE `mydb`.`one_to_one`
ADD UNIQUE INDEX `parent_id_UNIQUE` (`parent_id` ASC);
If we have TableA and TableB related by TableAB where TableAB has foreign keys for the first two table, then what's the go-to way of deleting an entry from TableA? Up to now if used a property such as IsActive with a bit to describe if the entry is still valid. However, that makes it a little problematic when there are "ghost entries" in the relation tables, such as TableAB.
How should I proceed?
One chaining table in question.
CREATE TABLE EntradaContadorCliente (
ClaveECC int AUTO_INCREMENT not null,
ClaveCliente int not null,
ClaveContador int not null,
ClaveEntrada int not null,
PRIMARY KEY (ClaveECC),
FOREIGN KEY (ClaveCliente) REFERENCES Cliente(ClaveCliente),
FOREIGN KEY (ClaveContador) REFERENCES Contador(ClaveContador),
FOREIGN KEY (ClaveEntrada) REFERENCES EntradaBitacora(ClaveEntrada)
);
Since TableA and TableB related by TableAB; which means TableAB is a chaining table. One way is to use ON DELETE CASCADE for cascading the delete operation on primary table.
Alternative is to, manually delete the entries from your chaining table once the entry has been deleted from primary table.
You can use a ALTER statement to re-create the FK constraint like
ALTER TABLE `TableAB` DROP FOREIGN KEY FK_KEY_Test;
ALTER TABLE `TableAB` ADD CONSTRAINT FK_KEY_Test FOREIGN KEY ('some_column')
REFERENCES `TableA` ('Test_column1') ON UPDATE CASCADE ON DELETE CASCADE;
From MySQL Documentation:
CASCADE: Delete or update the row from the parent table, and
automatically delete or update the matching rows in the child table.
Both ON DELETE CASCADE and ON UPDATE CASCADE are supported.
first you disable all foreign key with:-
alter table table_name
nocheck constraint fk_constraint
then you delete data in parent table.
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
I thought the point of ON DELETE CASCADE was that this wouldn't happen. :\ I have the following tables:
CREATE TABLE Tweets (
tweetID INTEGER NOT NULL AUTO_INCREMENT,
userID INTEGER NOT NULL,
content VARCHAR(140) NOT NULL,
dateTime TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
hasPoll INTEGER NOT NULL,
visible INTEGER NOT NULL DEFAULT 1,
PRIMARY KEY (tweetID),
FOREIGN KEY (userID) REFERENCES Users(userID)
ON DELETE CASCADE
);
CREATE TABLE Polls (
pollID INTEGER NOT NULL AUTO_INCREMENT,
tweetID INTEGER NOT NULL,
pollOptionText VARCHAR(300),
PRIMARY KEY (pollID),
FOREIGN KEY (tweetID) REFERENCES Tweets(tweetID)
);
The problem is that when I try to delete a Tweet which has a Poll attached to it, I get the following error (via Flask):
_mysql_exceptions.IntegrityError
IntegrityError: (1451, 'Cannot delete or update a parent row: a foreign key constraint fails (`twitter`.`polls`, CONSTRAINT `polls_ibfk_1` FOREIGN KEY (`tweetID`) REFERENCES `Tweets` (`tweetID`))')
Help please!
That is indeed the point of on delete cascade. You get the error, because your code doesn't declare on delete cascade from "poll" to "tweet".
CREATE TABLE Polls (
pollID INTEGER NOT NULL AUTO_INCREMENT,
tweetID INTEGER NOT NULL,
pollOptionText VARCHAR(300),
PRIMARY KEY (pollID),
FOREIGN KEY (tweetID) REFERENCES Tweets(tweetID)
ON DELETE CASCADE
);
This will delete rows in "Polls" when corresponding rows are deleted in "Tweets".
You have to put ON DELETE CASCADE after FOREIGN KEY (tweetID) REFERENCES Tweets(tweetID)
According to the MySQL Foreign Key Constraints reference:
CASCADE: Delete or update the row from the parent table, and
automatically delete or update the matching rows in the child table.
Both ON DELETE CASCADE and ON UPDATE CASCADE are supported.
Also, according to the MySQL Foreign Keys reference:
For storage engines other than InnoDB, it is possible when defining a
column to use a REFERENCES tbl_name(col_name) clause, which has no
actual effect, and serves only as a memo or comment to you that the
column which you are currently defining is intended to refer to a
column in another table.
So since the foreign key is from the child table to the parent table, it makes foo a parent table and Polls a child table, so deleting a row from Tweets will cascade deletions to Pools, providing you use InnoDB or some other storage engine that supports it.
UPDATE:
This error is because you have a relation between poll and twitter... without cascading you have to delete or update the polls removing the relation with the Tweet that will be deleted. Or use ON DELETE CASCADE:
CREATE TABLE Tweets (
tweetID INTEGER NOT NULL AUTO_INCREMENT,
content VARCHAR(140) NOT NULL,
PRIMARY KEY (tweetID)
);
CREATE TABLE Polls (
pollID INTEGER NOT NULL AUTO_INCREMENT,
tweetID INTEGER NOT NULL,
pollOptionText VARCHAR(300),
PRIMARY KEY (pollID),
FOREIGN KEY (tweetID) REFERENCES Tweets(tweetID)
ON DELETE CASCADE
);
INSERT INTO Tweets VALUES(1,'tweet');
INSERT INTO Polls VALUES(1,1,"pool");
DELETE FROM Tweets WHERE tweetID = 1;
You will surely get this error. you have to keep at least one record into tweets.