如果你的级联删除操作导致一个产品被删除,因为它是某个被删除的类别的成员,那么你的外键设置是有问题的。根据你提供的表格示例,你应该按照以下方式设置表格:
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;
这样,您可以删除一个产品或一个类别,只有categories_products中关联的记录才会被一起删除。级联操作不会向树形结构更高层级移动并删除父级产品/类别表。
例如:
products: boots, mittens, hats, coats
categories: red, green, blue, white, black
prod/cats: red boots, green mittens, red coats, black hats
如果你删除了“红色”类别,那么只有“红色”在类别表中的条目会被删除,以及两个条目prod/cats:“红色靴子”和“红色外套”。
删除操作不会进一步级联,也不会删除“鞋子”和“外套”这两个类别。
评论回复:
你仍然误解了级联删除的工作原理。它们只影响定义了“on delete cascade”的表。在本例中,级联删除是在“categories_products”表中设置的。如果你删除了“红色”类别,那么只有在categories_products中
category_id = red
的记录会进行级联删除。它不会触及任何“category_id = blue”的记录,并且不会继续前进到“products”表中,因为该表没有定义外键。
以下是一个更具体的示例:
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
+
假设你删除了分类 #2(蓝色):
DELETE FROM categories WHERE (id = 2);
DBMS会查找所有具有指向“categories”表的外键的表,并删除匹配ID为2的记录。由于我们只在products_categories
中定义了外键关系,因此在删除完成后,您将获得此表:
+
| product_id | category_id |
+
| 1 | 1 | // red mittens
| 2 | 1 | // red boots
+
在产品
表中没有定义外键,因此级联删除不会生效,所以你仍然可以看到列出的靴子和手套。只是没有'蓝色靴子'和'蓝色手套'了。