2010-06-03 54 views
1

这个问题让我很头疼。用JOIN删除?

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

分类是一个简单的基于语言的表:

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; 

什么我wan t要做的是更改查询也删除categories表中的代表性路径。不幸的是,我没有足够的SQL知识来做到这一点。我试图在查询之前做一个foreach循环的解决方法,但是无法删除,因为categories表被引用到categoriesPaths ... 由此说,我几乎卡住了。

如果有人想了解更多关于关闭表设计,下面是我在其中学会了从SlideShare上的引用:http://www.slideshare.net/billkarwin/sql-antipatterns-strike-back

回答

1

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

+0

我在查询中使用事务,但在此示例中未显示,因为我没有看到它会如何影响查询的结果? (假设查询应该在一个阶段完成) – Industrial 2010-06-03 15:56:13

+1

@Industrial通过一个事务,可以消除你的sql中的所有连接,而是发出一组单独的查询。它消除了一些复杂性,并且通过在发生失败时恢复更改来保证数据库保持一致。 – 2010-06-03 16:04:02

2

嗯,我会采取不同的路径。

  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