MySQL foreign key constraints, cascade delete
If your cascading deletes nuke a product because it was a member of a category that was killed, then you've set up your foreign keys improperly. Given your example tables, you should have the following table setup:
CREATE TABLE categories (
id int unsigned not null primary key,
name VARCHAR(255) default null
)Engine=InnoDB;
CREATE TABLE products (
id int unsigned not null primary key,
name VARCHAR(255) default null
)Engine=InnoDB;
CREATE TABLE categories_products (
category_id int unsigned not null,
product_id int unsigned not null,
PRIMARY KEY (category_id, product_id),
KEY pkey (product_id),
FOREIGN KEY (category_id) REFERENCES categories (id)
ON DELETE CASCADE
ON UPDATE CASCADE,
FOREIGN KEY (product_id) REFERENCES products (id)
ON DELETE CASCADE
ON UPDATE CASCADE
)Engine=InnoDB;
This way, you can delete a product OR a category, and only the associated records in categories_products will die alongside. The cascade won't travel farther up the tree and delete the parent product/category table.
e.g.
products: boots, mittens, hats, coats
categories: red, green, blue, white, black
prod/cats: red boots, green mittens, red coats, black hats
If you delete the 'red' category, then only the 'red' entry in the categories table dies, as well as the two entries prod/cats: 'red boots' and 'red coats'.
The delete will not cascade any farther and will not take out the 'boots' and 'coats' categories.
comment followup:
you're still misunderstanding how cascaded deletes work. They only affect the tables in which the "on delete cascade" is defined. In this case, the cascade is set in the "categories_products" table. If you delete the 'red' category, the only records that will cascade delete in categories_products are those where category_id = red
. It won't touch any records where 'category_id = blue', and it would not travel onwards to the "products" table, because there's no foreign key defined in that table.
Here's a more concrete example:
categories: products:
+----+------+ +----+---------+
| id | name | | id | name |
+----+------+ +----+---------+
| 1 | red | | 1 | mittens |
| 2 | blue | | 2 | boots |
+---++------+ +----+---------+
products_categories:
+------------+-------------+
| product_id | category_id |
+------------+-------------+
| 1 | 1 | // red mittens
| 1 | 2 | // blue mittens
| 2 | 1 | // red boots
| 2 | 2 | // blue boots
+------------+-------------+
Let's say you delete category #2 (blue):
DELETE FROM categories WHERE (id = 2);
the DBMS will look at all the tables which have a foreign key pointing at the 'categories' table, and delete the records where the matching id is 2. Since we only defined the foreign key relationship in products_categories
, you end up with this table once the delete completes:
+------------+-------------+
| product_id | category_id |
+------------+-------------+
| 1 | 1 | // red mittens
| 2 | 1 | // red boots
+------------+-------------+
There's no foreign key defined in the products
table, so the cascade will not work there, so you've still got boots and mittens listed. There's just no 'blue boots' and no 'blue mittens' anymore.
How do I use on delete cascade in mysql?
Here's what you'd include in your components table.
CREATE TABLE `components` (
`id` int(10) unsigned NOT NULL auto_increment,
`typeId` int(10) unsigned NOT NULL,
`moreInfo` VARCHAR(32),
-- etc
PRIMARY KEY (`id`),
KEY `type` (`typeId`)
CONSTRAINT `myForeignKey` FOREIGN KEY (`typeId`)
REFERENCES `types` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
)
Just remember that you need to use the InnoDB storage engine: the default MyISAM storage engine doesn't support foreign keys.
How to add on delete cascade option in mysql?
You have a typo in the Order
table. You have PRIMAY
where it should be PRIMARY
.
After correcting this, I tried creating the tables and all statements worked fine, including the last one.
Cascading deletes like ON DELETE CASCADE for a one time operation in MySQL
No, the simple answer is, no, there is no shortcut.
You either write down DELETE
statements to delete all the related rows in the related tables or you have defined foreign key constraints with ON DELETE CASCADE
.
Note that - as long as there are no circular paths in the foreign key relationships - it is possible to use a single DELETE
statement that deletes from multiple tables:
DELETE a, b, c, d
FROM a
LEFT JOIN b ON b.a_id = a.a_id
LEFT JOIN c ON c.a_id = a.a_id
LEFT JOIN d ON d.b_id = b.b_id
WHERE
a.a_id = 1 ;
Mysql on delete cascade not working
The constrain you have now will delete from tags_files
when a referenced id will be deleted on files
.
If you need to automatically delete from files
when you delete from tags_files
, then the constrain must be on files
table.
Like this:
DROP TABLE IF EXISTS `files`;
CREATE TABLE IF NOT EXISTS `files` (
`id` VARCHAR(36) NOT NULL,
`name` VARCHAR(50) NOT NULL,
`extension` VARCHAR(5) NOT NULL,
`version` INT(11) NOT NULL,
`date` DATE NOT NULL,
PRIMARY KEY (`id`),
CONSTRAINT FOREIGN KEY (`id`) REFERENCES `tags_files` (`file_id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
and TagsFiles:
DROP TABLE If EXISTS `tags_files`;
CREATE TABLE IF NOT EXISTS `tags_files` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`tag_id` INT(11) NOT NULL,
`file_id` VARCHAR(36) NOT NULL,
PRIMARY KEY (`id`)
)ENGINE=InnoDB DEFAULT CHARSET=utf8;
Well you get an error in above example because MySQL don't allow constraints for varchar type. If you change it to char you can. But you also need to change the sequence of the execution queries due to constrains. Do like this:
DROP TABLE IF EXISTS `files`;
DROP TABLE If EXISTS `tags_files`;
CREATE TABLE IF NOT EXISTS `tags_files` (
`id` INT(11) NOT NULL,
`tag_id` INT(11) NOT NULL,
`file_id` char(36) NOT NULL,
PRIMARY KEY (`file_id`)
)ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE IF NOT EXISTS `files` (
`id` char(36) NOT NULL,
`name` VARCHAR(50) NOT NULL,
`extension` VARCHAR(5) NOT NULL,
`version` INT(11) NOT NULL,
`date` DATE NOT NULL,
PRIMARY KEY (`id`),
CONSTRAINT FOREIGN KEY (`id`) REFERENCES `tags_files` (`file_id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Related Topics
How to List the Primary Key of a SQL Server Table
How to Import a Json File into Postgresql
SQL Server - Transactions Roll Back on Error
Entity Framework VS Linq to SQL VS Ado.Net With Stored Procedures
How to Set Table Name in Dynamic SQL Query
Identity Column Value Suddenly Jumps to 1001 in SQL Server
What's the Best Way to Join on the Same Table Twice
How to Create a Unique Index on a Null Column
Add Foreign Key Relationship Between Two Databases
Converting Epoch Timestamp to SQL Server(Human Readable Format)
Key Value Pairs in Relational Database
How to Restore a Dump File from MySQLdump
Sql: Find the Max Record Per Group
How to Create Composite Primary Key in SQL Server 2008
How to Select an Entire Row Which Has the Largest Id in the Table