回答
當行數不是太大時,erikkallen的遞歸方法起作用。
這是一個使用臨時表來收集所有孩子的選擇:
create table #nodes (id int primary key)
insert into #nodes (id) values (@delete_id)
while @@rowcount > 0
insert into #nodes
select distinct child.id
from table child
inner join #nodes parent on child.parentid = parent.id
where child.id not in (select id from #nodes)
delete
from table
where id in (select id from #nodes)
它開始與@delete_id該行並從那裏下降。 where語句是爲了防止遞歸;如果你確定沒有,你可以把它放棄。
取決於您如何存儲您的層次結構。如果您只有ParentID,那麼它可能不是您採取的最有效的方法。爲了便於操縱子樹,你應該有一個附加列Parents
是wouls存儲所有父ID,如:
/1/20/25/40
這樣你就可以簡單地通過獲得所有子節點:
where Parents like @NodeParents + '%'
第二種方法
而不僅僅是ParentID您可能也有left
和right
值。以這種方式插入會更慢,但選擇操作速度非常快。特別是隨着子樹節點打交道時... http://en.wikipedia.org/wiki/Tree_traversal
第三種方法
檢查遞歸CTE的,如果你使用SQL 2005+
第四種方法
如果使用SQL 2008,檢查HIERARCHYID型。它爲您的案例提供了足夠的可能性。 http://msdn.microsoft.com/en-us/magazine/cc794278.aspx
添加觸發器表中這樣
創建mytable上進行刪除作爲 觸發TD_MyTable - 刪除的一個子級 從刪除d內刪除M於D.ID加入myTable的中號 = M.ID
每次刪除都會調用同一張表上的刪除,反覆調用觸發器。在線檢查書籍是否有其他規則。可能會限制觸發器可以嵌套的次數。
ST
取決於您的數據庫。如果您使用的是Oracle,你可以做這樣的事情:
DELETE FROM Table WHERE ID IN (
SELECT ID FROM Table
START WITH ID = id_to_delete
CONNECT BY PRIOR.ID = ParentID
)
ETA:
沒有CONNECT BY,它變得有點棘手。正如其他人所說,觸發器或級聯刪除約束可能是最簡單的。
添加外鍵約束。下面的示例適用於MySQL的(syntax reference):
ALTER TABLE yourTable
ADD CONSTRAINT makeUpAConstraintName
FOREIGN KEY (ParentID) REFERENCES yourTable (ID)
ON DELETE CASCADE;
這將在數據庫級別上運行,數據庫管理系統將確保一旦行被刪除,所有引用行將被刪除了。
在SQL Server上:使用遞歸查詢。鑑於CREATE TABLE TMP(ID INT,家長INT),使用
WITH x(Id) AS (
SELECT @Id
UNION ALL
SELECT tmp.Id
FROM tmp
JOIN x ON tmp.Parent = x.Id
)
DELETE tmp
FROM x
JOIN tmp ON tmp.Id = x.Id
你想要的是這些表之間referential integrity。
- 1. 刪除分離的數據庫SQL 2008
- 2. 從SQL表中刪除數據
- 3. 從SQL Server數據庫中的所有表數據刪除,除了一些表
- 4. SQL查詢從表中定義的表中刪除數據
- 5. 訂購父/子 - SQL中的分層數據表
- 6. 單個表中的分層數據
- 7. 從表中刪除數據
- 8. 的SQL Server:存儲分層ACL數據
- 9. Linq to SQL的分層數據綁定
- 10. 從分層集合中刪除對象
- 11. 如何刪除MS SQL數據庫中的部分重複項?
- 12. 根據sql條件從表中刪除
- 13. SQL刪除大量數據
- 14. SQL刪除Extra列數據
- 15. 刪除數據庫SQL PHP
- 16. SQL數據庫刪除
- 17. 刪除SQL Server數據庫
- 18. 有道創建/更新/刪除分層數據
- 19. MVC 5實體框架6 - 刪除嵌套/分層數據
- 20. 如何刪除SQL CE中表中的所有數據?
- 21. 從SQL Server 2008中的數據透視表中刪除NULL
- 22. 刪除最外層列表
- 23. 刪除層疊到表
- 24. StringTemplate中的分層數據
- 25. ETL中的分層數據
- 26. 充分利用自參照表分層數據在SQL 2005
- 27. 刷卡刪除沒有刪除底層數據結構
- 28. 基於分層日期時間的刪除T-SQL
- 29. 在Tastypie中表示分層數據
- 30. 從ODBC(SQL Server)中刪除數據庫名稱表列表
NO,我不想整父母鏈存儲在列,因爲不斷有家長參與改變。並且很難跟蹤所有這些。 不能這樣做,因爲它是現在? – markiz 2009-05-19 12:16:27
什麼是您的層次結構數據的主要操作?它是插入,更新還是讀取? – 2009-05-19 12:18:09
我傾向於同意第一種方法 - 我們已經得到了我們正在做同樣事情的分層數據表。它有助於擺脫孩子,並且如果您需要對樹進行基於路徑的處理(例如,必須快速返回父母的所有孩子進行計算),這也會有所幫助。 我們最初嘗試使用觸發器來保持這一點,但真正發現添加大量數據時的性能影響是令人望而卻步的。 – 2009-05-19 13:05:18