我有两个SQL表,'product'和'tags'。它们具有 n:m 关系,使用第三个表"product_tags"。
我想一起删除一些产品和相应的标签。
假设我有 products.product_id=3,该产品有 tags.tag_id=3,tags.tag_id=5
product_tags表
product_id 3 tag_id 3 product_id 3 tag_id 5
delete from tags where tag_id in (select product_tags.tag_id from product_tags where product_id =3);
delete from tags where tag_in = any (select product_tags.tag_id from product_tags where product_id=3);
两者都会产生
0 row(s) affected, 1 warning(s): 1242 Subquery returns more than 1 row
那么,我该如何才能做到这一点呢?
首先,您很可能希望删除未与其他产品一起使用的标签。 例如,如果带有tag_id = 3
的标签也与其他产品一起使用,比如说product_id = 1
那么您应该删除此标签。
其次,如果使用外键强制实施正确的父子关系,则必须按正确的顺序从表中删除行。首先,您应该从product_tags
中删除行。
话虽如此,您安全删除产品以及未使用标签的代码可能看起来
DELIMITER //
CREATE PROCEDURE delete_product(IN _product_id INT)
BEGIN
DROP TEMPORARY TABLE IF EXISTS tmp_tags_to_be_deleted;
START TRANSACTION;
CREATE TEMPORARY TABLE tmp_tags_to_be_deleted(tag_id INT PRIMARY KEY);
INSERT INTO tmp_tags_to_be_deleted
SELECT tag_id
FROM product_tags t
WHERE product_id = _product_id
AND NOT EXISTS
(
SELECT *
FROM product_tags
WHERE tag_id = t.tag_id
AND product_id <> t.product_id
);
DELETE
FROM product_tags
WHERE product_id = _product_id;
DELETE t
FROM tags t JOIN tmp_tags_to_be_deleted x
ON t.tag_id = x.tag_id;
DELETE
FROM products
WHERE product_id = _product_id;
COMMIT;
END//
DELIMITER ;
用法:
CALL delete_product(3);
这是 SQLFiddle 演示