在多对多关系中删除正确

Posted

技术标签:

【中文标题】在多对多关系中删除正确【英文标题】:Deleting correct in a many-to-many relationship 【发布时间】:2014-03-05 15:45:26 【问题描述】:

我有一个关于多对多关系的简短问题。 这是我的表格:

+---------+----------------+
| film_id | title          | 
+---------+----------------+
|       1 | Apocalypse Now |
+---------+----------------+


+-------------+----------------------+
| category_id | name                 | 
+-------------+----------------------+
|           1 | cool category        |
+-------------+----------------------+
|           2 | not so cool category |
+-------------+----------------------+

+---------+-------------+
| film_id | category_id |
+---------+-------------+
|       1 |           1 |
+---------+-------------+
|       1 |           2 |
+---------+-------------+

如您所见,film- 和 category-table 中有 FK 在 film_category-table 中。

我想要什么:如果要删除category,那么film_category 中出现category_id 的所有条目也应该被删除。但不是相关的films!除此之外:这应该在删除film 时起作用,反之亦然! (这正是我的问题)

我的问题:我可以仅使用 FK 定义解决问题,还是必须在删除 filmcategory 之前手动删除 film_category 表中的所有条目?

【问题讨论】:

您可以通过对外键执行正常的ON DELETE CASCADE 引用触发操作来实现此目的。 当我这样做然后删除category时,相关的film也会被删除。 你能发布你的表和外键定义吗,in the sql fiddle 我已经完成了,当一个类别被删除时,它只会删除 film_category 中具有该 category_id 的行,而电影表保持不变。跨度> 我的film_category-table 与film_id+category_id 有一个复合PK。这是我看到的唯一区别:/ 这应该没什么区别。 Example on SQL Fiddle. 【参考方案1】:

您的表格应如下所示。在电影表中删除应该删除电影类别具有相同id的行,反之亦然。

CREATE TABLE `film` (
  `film_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `title` varchar(255) NOT NULL DEFAULT '',
  PRIMARY KEY (`film_id`)
) ENGINE=InnoDB;

CREATE TABLE `category` (
  `category_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(255) NOT NULL DEFAULT '',
  PRIMARY KEY (`category_id`)
) ENGINE=InnoDB;

CREATE TABLE `film_category` (
 `film_category_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
 `film_id` int(10) unsigned NOT NULL DEFAULT '0',
 `category_id` int(10) unsigned NOT NULL DEFAULT '0',
 PRIMARY KEY (`film_category_id`),
 KEY `film_id` (`film_id`),
 KEY `category_id` (`category_id`),
 CONSTRAINT `film_category_ibfk_2` FOREIGN KEY (`category_id`) REFERENCES `category` (`category_id`) ON DELETE CASCADE,
 CONSTRAINT `film_category_ibfk_1` FOREIGN KEY (`film_id`) REFERENCES `film` (`film_id`) ON DELETE CASCADE
) ENGINE=InnoDB;

您还应该能够将以下内容用于film_category:

CREATE TABLE `film_category` (
  `film_id` int(10) unsigned NOT NULL DEFAULT '0',
  `category_id` int(10) unsigned NOT NULL DEFAULT '0',
  PRIMARY KEY (`film_id`,`category_id`),
  CONSTRAINT `film_category_ibfk_1` FOREIGN KEY (`film_id`) REFERENCES `film` (`film_id`) ON DELETE CASCADE,
  CONSTRAINT `film_category_ibfk_2` FOREIGN KEY (`category_id`) REFERENCES `category` (`category_id`) ON DELETE CASCADE
) ENGINE=InnoDB;

【讨论】:

与我的表不同的是你的film_category有自己的ID,只有这个是PK。我的film_category 没有自己的ID,它与film_id+category_id 有一个复合PK。那么,当我删除category 时,您认为这也是它删除相关film 的问题吗? 我在上面添加了带有复合主键的film_category 表示例。如果删除 category.category_id 1,那么它应该只删除第 1,1 行,但在 film_category 表中保留 1,2。

以上是关于在多对多关系中删除正确的主要内容,如果未能解决你的问题,请参考以下文章

Entity Framework 6 Recipes 2nd Edition(10-9)译 -> 在多对多关系中为插入和删除使用存储过程

如何在多对多表上级联删除

如何在多对多关系中更新日期

在多对多关系中使用“And Where”

在多对多关系中命名表 laravel

Django:在多对多关系中交换元素