2017-09-12 55 views
3

我正在一個側項目,以刪除行及其在自引用表中的所有的後代,我使用 遞歸CTE這樣的觸發器中:使用CTE在自引用表中遞歸刪除行。過程如何進行?

CREATE TRIGGER dbo.tr_Comment_Delete 
    ON dbo.Comment INSTEAD OF DELETE 
AS 
    ;WITH IDs AS (
     SELECT id FROM DELETED 
     UNION ALL 
     SELECT c.id 
     FROM Comment AS c INNER JOIN IDs AS i 
     ON c.parent_comment_id = i.id 
    ) 
    DELETE FROM Comment 
    WHERE id IN (SELECT id FROM IDs); 
GO 

這是自引用表

enter image description here

雖然我有這樣的代碼工作正常,它是指在其中做一些情形之一的,但你不能肯定 它是如何工作的。

更準確地說,我想知道的是,通過使用此遞歸CTE(ID),我能夠避免參考完整性錯誤 當我嘗試刪除具有子註釋的評論時?

什麼是評論被刪除的過程/順序?

採取的評論此層次結構爲例:

3-> 8-> 13 

這裏ID 3的評論是根評論。評論8是對評論3的回覆,就像評論13是對評論8的回覆。

刪除過程如何實際發生?

P.S.我嘗試添加一個表格,我在其中插入了他們計算的ID。不幸的是我無法理解它。 這些都是這種表的結果:

id ins-date 
3 2017-09-12 11:48:38.037 
8 2017-09-12 11:48:38.037 
13 2017-09-12 11:48:38.037 
13 2017-09-12 11:48:38.037 
8 2017-09-12 11:48:38.037 
13 2017-09-12 11:48:38.037 
+0

我認爲dba.se這個優秀的問題是重要的levant:[唯一索引更新和統計行修改計數器](https://dba.stackexchange.com/q/185551/57105)。檢查你的'DELETE'的實際執行計劃,它會告訴你很多細節。 –

回答

1

我想你看到的複雜性,其中不存在了。

你的錯誤是:

Deleting rows recursively in self-referencing CTE

有沒有這樣的事情遞歸DELETE。只有SELECT可以。

所以處理也很簡單:

  1. 計算所有要刪除的行中SELECT與recurcive CTE

  2. DELETE他們都與一個操作

這是所有

+0

是的,你說得對。也許我在標題中表達的方式有點誤導,因爲遞歸計算的是ID,但是在使用觸發器刪除註釋的方式中必須有某種遞歸過程。當然,它們不能一次全部刪除而不會導致引用完整性錯誤?如果我沒有弄錯,第一次嘗試刪除id 3的註釋,CTE應該返回這些id:'3,8,13'。如果刪除一次全部發生,那麼試圖刪除評論3不應該被允許,因爲它有一個子評論(8) – eddy

+0

**「當然,它們不能一次全部刪除而不會引起參考完整性錯誤」 ** - 爲什麼? @eddy,你寫了正確的SELECT CTE計算增量,沒有嵌套事務,SQLServer **必須**一次刪除所有記錄。 (事實上​​,我記得有些RDBMS的觸發器是「逐行」工作的,與髒讀結合可能會導致_strange_事情發生。) – Ingaz

+0

實際上,您可以將'DELETE'替換爲'INSERT'和' SELECT'與'NOT EXISTS':1)創建表DELETED_ROWS 2)'ALTER TRIGGER' - 而不是'DELETE'您INSERT INTO DELETED_ROWS',3)'CREATE VIEW'用於COMMENTS C WHERE NOT EXISTS(SELECT * FROM DELETED_ROWS D WHERE D.id = C.id)'。實際上,SQLServer做的是類似的事情 - 它不會立即清除發佈的'DELETE'上的所有內容,它會將記錄標記爲過時。 – Ingaz