我有一个包含 3 个表的数据库:
- 用户
- Users_cards
- 卡片
表 users_cards
有两列:
- user_id(是Users.id的外键)
- card_id(是 Cards.id 的外键)
users
和cards
表有自己的id作为主键,users_cards
的两列是它们的外键,级联删除选项,所以当我从 cards
中删除一张卡时,它也会从 users_cards
中删除,与 users
相同。
而且,我希望当我删除 users_cards
表的一行时,如果该卡没有更多用户,也就是说,如果该行是 card_id< 的唯一行
出现在表格中,它也必须从 cards
中删除。
实现此目标的最佳方法是什么?可以“自动”完成,还是每次从 users_cards
中删除一行时都必须检查?
最佳答案
Can it be done "automatically" or do I have to check every time I delete one row from users_cards this?
自动取决于你的意思。 我会使用触发器:
DELIMITER $$
CREATE DEFINER=CURRENT_USER TRIGGER `name_of_this_trigger`
AFTER DELETE ON `users_cards` FOR EACH ROW
BEGIN
DELETE FROM `cards` WHERE `id` NOT IN (SELECT DISTINCT `card_id` FROM `users_cards`);
END $$
DELIMITER ;
如果你在你的数据库上执行它,它会添加一个触发器来运行并检查无用户卡,并在每次对 users_cards
表进行 DELETE 查询后删除它们而不会造成任何额外的麻烦。
但是,如果 users_cards
已被级联事件删除,它不会运行,因此无法删除任何可能没有用户的卡片。
所以,你可以做两件事。无:垃圾将在 users_cards
的下一个 DELETE 查询中被清除。或者;您可以添加另一个触发器,它在 users
表上的 DELETE 查询之后运行,就像这样(删除由于级联而现在没有 users_cards
的任何潜在卡片删除源自用户
):
DELIMITER $$
CREATE DEFINER=CURRENT_USER TRIGGER `name_this_very_trigger`
AFTER DELETE ON `users` FOR EACH ROW
BEGIN
DELETE FROM `cards` WHERE `id` NOT IN (SELECT DISTINCT `card_id` FROM `users_cards`);
END $$
DELIMITER ;
仅供引用:如果您注意到,触发器声明后只有一个语句,所以您甚至不需要 BEGIN ... END
block ,这意味着 DELIMITER
废话也不必了。
如果有帮助,请告诉我!
ps.:看在上帝的份上; 请不要使用复数表名。您是在命名存储在表中的实体而不是表本身。
关于mysql删除与其他元素没有链接的元素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43485092/