我的数据库中有以下三个表:
cases
id INT
description TEXT
tags
id INT
name TEXT
case_tag
id INT
case_id INT
tag_id INT
单个案例可以有任意数量的标签,并且一个标签可以属于任意数量的案例。
如果删除某个案例,我想删除 tags
表中链接到该案例的所有标签,前提是(且仅当)它们未链接到任何其他案例。我该如何实现这一目标?
最佳答案
假设您使用的是 InnoDB,请在 case
和 case_tag
之间创建一个 ON DELETE CASCADE 引用操作。然后,在删除所需的 case
后,相应的 case_tag
行将自动删除,剩下的就是简单地:
DELETE FROM tag WHERE tag_id NOT IN (SELECT tag_id FROM case_tag);
如果需要,您甚至可以从触发器中执行此操作,但此方法更适合某种后台“清理”过程,因为它会清除所有多余的标签,而不仅仅是与最后一个相关的标签已删除案例
。
另一种方法是预先选择与要删除的案例相关的标签,然后尝试仅删除它们。
附带建议:
- TEXT(BLOB 的一种形式)对于
tag.name
来说可能有点过分 - 请改用 VARCHAR。 - 您可能不需要 surrogate key
case_tag.id
。 - 考虑在
case_tag {tag_id, case_id}
上添加索引(即与我的 SQL Fiddle 中的 PK 相反)。将tag_id
置于索引的前沿对于在tag_id
上强制执行 FK、选择给定标签的案例以及 DELETE 非常重要多于。我们包含case_id
以使索引更有可能 cover查询,并且case_id
无论如何都会包含在索引中,因为 clustered 中的二级索引表包含 PK 的副本。 - 命名表时使用单数(或者至少不要混合使用复数和单数)。
- 在 PK 字段名称中使用前缀。这有些争议,但根据我的经验,增加了 ER 模型、SQL 和 DAL 的可读性。 .
关于mysql - 有条件地从 MySQL 数据库中删除标签,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16795932/