【问题标题】:Deleting with JOIN?用 JOIN 删除?
【发布时间】:2010-06-03 15:43:06
【问题描述】:

这个问题让我很头疼。

我的数据库中有两个表,它们借助称为“闭包表”的设计来解决类别排序问题。第一个表名为categories,另一个表名为categoriesPaths

Categories 只是一个基于语言的表格:

id | name
----------------
0  | Category 1
1  | Category 2

CategoriesPaths 看起来像这样:

parent | children | level
-----------------------
1     | 1         | 0
1     | 2         | 1
2     | 2         | 0

要删除路径及其最终的子节点,我运行以下查询:($top 是删除将开始的最高父节点级别)

DELETE d FROM CategoriesPaths children
JOIN CategoriesPaths a USING (children)
WHERE a.parent = $top;

我想要做的是更改查询以同时删除categories 表中的代表性路径。不幸的是,我没有足够的 SQL 知识来执行此操作。我试图在查询之前使用 foreach 循环解决方法,但无法删除,因为 categoriestable 引用了 categoriesPaths... 话虽如此,我几乎被困住了。

如果有人想了解更多关于封闭表设计的信息,请参考我从中学到的幻灯片共享:http://www.slideshare.net/billkarwin/sql-antipatterns-strike-back

【问题讨论】:

    标签: mysql join sql-delete


    【解决方案1】:

    好吧,我会采取不同的方式。

    1. 使用要删除的所有项目的 ID 创建一个临时表
    2. 从临时表中删除 CategoriesPaths
    3. 从临时表中删除类别
    4. 删除临时表。

    像这样:

    -- not tested
    CREATE TABLE tmp_to_delete
    AS SELECT children.children
    FROM CategoriesPaths children
    JOIN CategoriesPaths a USING (children)
    WHERE a.parent = $top;
    
    DELETE FROM CategoriesPaths WHERE children IN (SELECT children FROM tmp_to_delete)
    DELETE FROM Categories WHERE id IN (SELECT children FROM tmp_to_delete)
    
    DROP TABLE tmp_to_delete
    

    【讨论】:

      【解决方案2】:

      为什么不使用事务? http://www.firstsql.com/tutor5.htm

      【讨论】:

      • 我在查询中使用事务,但在此示例中未显示,因为我看不到它如何影响查询结果? (假设我应该在一个阶段进行查询)
      • @Industrial 通过事务,您可以消除 sql 中的所有连接,而是发出一组单独的查询。它消除了一些复杂性,并且还通过在出现故障时恢复更改来保证您的数据库保持一致。
      猜你喜欢
      • 2013-03-09
      • 1970-01-01
      • 2010-10-13
      • 2011-02-15
      相关资源
      最近更新 更多