mysql 删除没有 link 的元素

mysql delete element when it has no link with others

我有一个包含 3 tables 的数据库:

tableusers_cards有两列:

userscardstable有自己的id作为主键,users_cards的两列是它们的外键,cascade选项开启删除,所以当我从 cards 中删除一张卡片时,它也会从 users_cards 中删除,与 users 相同。

而且,我希望当我删除 users_cards table 的一行时,如果该卡没有更多用户,也就是说,如果该行是 card_id出现在table中,它也必须从中删除cards

实现此目标的最佳方法是什么?可以做到 "automatically" 还是我每次从 users_cards 中删除一行时都必须检查?

请尝试以下...

CASE ( SELECT COUNT( * )
       FROM users_cards
       WHERE card_id = targetID )
    WHEN 0 THEN
        DELETE
        FROM Cards
        WHERE id = targetID;
    WHEN 1 THEN
        DELETE Cards,
               users_cards
        FROM cards
        JOIN users_cards
        WHERE Cards.id = users_cards.card_id
          AND Cards.id = targetID;
    ELSE
        *** Delete a user_card ***
END

此语句将计算 users_cards 中剩余的条目数,其中 card_id 等于目标 ID。

如果有 none,它检测到没有对应的 UsersCard,然后将其删除。

如果有,则删除 Cardsusers_cards 中与目标 ID 对应的条目。

如果不止一个,那么请使用您现有的 DELETE 语句来描述该场景。

如果您有任何问题或意见,请随时post发表相应的评论。

进一步阅读

Mysql - delete from multiple tables with one query(佩卡的回答)

https://dev.mysql.com/doc/refman/5.7/en/delete.html(对于单个和多个 table DELETE 语法)

https://dev.mysql.com/doc/refman/5.7/en/case.html(对于CASE

您必须在设计时设置 属性 table 当主 table 中的行被删除时应该对子 table 执行什么操作。

ON DELETE CASCADE 也会从子 table 中删除相应的行。 ON UPDATE CASCADE 也会更新子 table 中对应行的参考键值。

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;

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 ;

如果你在你的数据库上执行它,它会添加一个触发器 运行s 并检查无用户卡,并在 [=12= 上的每个 DELETE 查询后删除它们而不会造成任何额外的麻烦] table。 但是,如果 users_cards 已被级联事件删除,它不会 运行,因此无法删除任何可能没有用户的卡片。 所以,你可以做两件事。无:垃圾将在 users_cards 的下一个 DELETE 查询中被清除。要么;您可以添加另一个触发器,在 users table 上的 DELETE 查询之后 运行s 像这样(删除任何现在没有 users_cards 到期的潜在卡片到源自 users 的级联 DELETE):

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 块,这意味着 DELIMITER 废话也没有必要.

如果有帮助,请告诉我!

ps.: 看在上帝的份上; 请不要使用复数 table 名称。 您正在命名存储在 table 中的实体,而不是 table 本身。