mysql 删除没有 link 的元素
mysql delete element when it has no link with others
我有一个包含 3 tables 的数据库:
- 用户
- Users_cards
- 卡片
tableusers_cards
有两列:
- user_id(是Users.id的外键)
- card_id(是Cards.id的外键)
users
和cards
table有自己的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,它检测到没有对应的 Users
的 Card
,然后将其删除。
如果有,则删除 Cards
和 users_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
语法)
您必须在设计时设置 属性 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 本身。
我有一个包含 3 tables 的数据库:
- 用户
- Users_cards
- 卡片
tableusers_cards
有两列:
- user_id(是Users.id的外键)
- card_id(是Cards.id的外键)
users
和cards
table有自己的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,它检测到没有对应的 Users
的 Card
,然后将其删除。
如果有,则删除 Cards
和 users_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
语法)
您必须在设计时设置 属性 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 本身。