删除数据库记录及其相关记录

时间:2013-05-12 08:44:48

标签: sql sql-server-ce

我有一个产品,类别和“productsInCategories”的数据库,如下所示:


用户

id█  name  ▌
▀▀█▀▀▀▀▀▀▀▀▌
1 █  john  ▌
69█  jane  ▌

产品

id█  name  █ cost █description▌
▀▀█▀▀▀▀▀▀▀▀█▀▀▀▀▀▀█▀▀▀▀▀▀▀▀▀▀▀▌
21█snickers█  23  █ foo       ▌
34█  mars  █  20  █ bar       ▌
37█  daim  █  21  █ oofrab    ▌
79█ banana █  8   █ foobar    ▌
80█  apple █  10  █ barfoo    ▌

分类

id█  userId █   name  ▌
▀▀█▀▀▀▀▀▀▀▀▀█▀▀▀▀▀▀▀▀▀▌
10█    69   █chocolate▌
55█    69   █favorites▌
20█    1    █ fruit   ▌

ProductsInCategories

categoryId█productId▌
▀▀▀▀▀▀▀▀▀▀█▀▀▀▀▀▀▀▀▀▌
    10    █   21    ▌
    10    █   34    ▌
    20    █   79    ▌
    20    █   80    ▌
    55    █   21    ▌
    55    █   37    ▌

这会产生一些可以看作的东西:

Users
   john
      fruit
         banana
         apple
   jane
      chocolate
         snickers
         mars
         daim
      favorites
         snickers
         daim

当我想获得某个类别的所有产品时,我会做类似的事情:

SELECT *
FROM Products
        INNER JOIN ProductsInCategories
        ON Products.Id=ProductsInCategories.product
        WHERE category=@0
,@0=categoryId

这一切都正常,插入或删除产品非常简单。 但是我现在有一个问题,我无法解决这个问题。

删除类别。我将如何继续这样做?我已经工作了几个小时,但似乎无法让它工作。 如果用户删除某个类别,我希望该类别中仅存在 的所有产品与相关的productInCategories记录一起删除。 如果说用户“Jane”删除了她的“巧克力”类别,那么我想删除产品“火星”而不是“窃笑”或“火星”,因为它们也存在于“收藏夹”类别中

2 个答案:

答案 0 :(得分:4)

除非您在架构中设置了级联删除,否则您需要使用3个删除语句,每个表一个。

-- Delete category 10 from Categories table.
DELETE FROM Categories WHERE Id=10;

-- Delete category 10 from ProductsInCategories table.
DELETE FROM ProductsInCategories WHERE CategoryId=10;

-- Delete all products that are no longer in a category    
DELETE Products
FROM Products
LEFT JOIN ProductsInCategories
  ON ProductId=Products.Id
WHERE ProductId IS NULL;

An SQLfiddle to test with

答案 1 :(得分:1)

一些让您前进的pseodocode:

 Delete from ProductsIncategories where category = X

 Delete from products where productID in (
    select productID from
        products left outer join productsincategories 
        on products.productID = productsincategories.productID
    where 
        productsincategories.categoryid is null
 )

 delete from categories where category = x
  1. 如果您首先删除类别中的产品,则取决于其他表格,并且不依赖于它。

  2. 现在在任何类别中查找产品 - 这些只是要删除的类别 - 这是通过从产品到产品类别的左外部连接来完成的 - 这给出了产品的所有行,如果它们是null没有类别产品的匹配记录

  3. 删除类别本身,因为现在没有任何内容链接到它。

  4. 作为旁注,请考虑不要仅删除此类别中的产品,而是提供这些产品的报告供人们审核和清理。在我看来,工作可能会经常丢失。也许至少在你删除之前给他们确认的机会

    另请注意,中间声明将删除不在某个类别中的每个产品..在这样的问题上有两种思想流派

    1. 任何不属于某一类别的产品都是错误的,所以当你能够
    2. 时,将它们全部清理干净
    3. 产品可能没有类别的原因有多种,这对我没用!
    4. 如果您只想删除仅属于此类别的产品且毯子删除效果不佳,那么这样的内容可能有所帮助:

      select productID form
      from
          products as p
          inner join productsincategories as pic
              on PIC.productid = p.productid
          inner join (
              select distinct productID from productsincategories 
              where categoryid = X
          ) as t
              on t.productid = p.productid
       group by 
          productid
       having 
          count(*) = 1
      

      这是使用Joachim Isaksson的小提琴选择实际行动(现在约翰希姆+ 1'你的回答)

      http://sqlfiddle.com/#!3/5a744/22

      LEFT OUTER JOINS - 快速笔记

      table a
      id
      1
      2
      
      
      table b
      aID   value
      1     x
      1     y
      
      
      a left outer join b (select * from a left outer join b on a.id = b.aID)
      id  aID value
      1   1   x
      1   1   y
      2   NULLNULL
      
      b left outer join a (select * from b left outer join a on a.id = b.aID)
      aID value id
      1   x     1
      1   y     1
      

      左外连接为您提供左侧表格中的所有内容以及右侧表格中的匹配项。如果左表中有一行而右表没有,则右表中的所有列都会得到NULL。希望有帮助,但值得谷歌搜索和实验,以适应。

      当您想要查看所有商品的销售情况时,它非常有用,但您希望获得商品列表是否有销售。或者就像我们在这里使用它来查找一个表中没有在另一个表中的所有内容,只选择“右”表为空的位置