2010-06-30 115 views
0

我有一個非常通用的一套存儲所有的數據,其工作出色的三個表(我們所說的少量數據在這裏)SQL服務器:遞歸存儲過程

DataContainer - 管理「記錄」

PK - DataContainerId 
FK - ParentDataContainerId 
FM - ModelEntityId 

DataInstance - 管理版本

PK - DataInstanceId 
FK - DataContainerId 
    IsCurrent [bit] NOT NULL CONSTRAINT [DF_DataInstance_IsCurrent] DEFAULT ((1)), 
    ModifiedBy [nvarchar](50) NOT NULL CONSTRAINT [DF_DataInstance_ModifiedBy] DEFAULT (suser_sname()), 
    ModifiedDateTime [datetime] NOT NULL CONSTRAINT [DF_DataInstance_ModifiedDateTime] DEFAULT (getdate()), 

DataValue

PK - DataValueId 
FK - DataInstanceId 
FK - ModelEntityId 
    ValueText --the actual values 

問題:當一條記錄被刪除,我需要標記爲刪除所有子記錄。

嘗試

--flag current record as deleted 
update DataInstance 
set IsCurrent = 0 
Where DataContainerId = @DataContainerId 
And (@ModelContainerId is null or @ModelContainerId = ModelContainerId) 

--remove all child records 
declare db_cursor for 
select sc.DataContainerId as 'ChildDataContainerId' from DataInstance di 
inner join datacontainer dc on dc.datacontainerId = di.datacontainerId 
where parentdatacontainerId = @DataContainerId 

declare @ChildDataContainerId int 
open db_cursor 
fetch next from db_cursor into @ChildDataContainerId 

while @@fetch_status = 0 
begin 
    exec dataInstance_Delete null, @ChildDataContainerId --current sp 
end 

close db_cursor 
deallocate db_cursor 

的問題是,我不能使用遊標recursivly(因爲我得到一個錯誤,光標已經打開),所以這個SP只會工作一個級別深度。

有沒有更狡猾的做法呢?

+0

存儲所有的數據在一個表中,然後使用遊標來處理你的記錄,你應該從脫身的做法。當你忽略規範化數據的智慧以及SQL設計的設置邏輯的力量時,你就會頭痛不已。也許你應該考慮爲了自己的利益重構以後的重構? – Tahbaza 2010-06-30 03:45:38

+1

由於我討厭貼在泥土中,只是發表負面評論,然後走開這裏,如果您決定繼續前進,則可以解決您的問題:使用SQL以外的應用程序編程語言進行遞歸。它們通常不受遞歸調用規則的限制,如果您更喜歡行邏輯,則可以使用記錄集或同等方法更輕鬆地處理記錄。快樂的編碼... – Tahbaza 2010-06-30 03:49:19

+0

我不得不同意Tahbaza,但如果你堅持採取這條路線,我會使用觸發器。觸發器可以遞歸執行(達到某個(可配置的我相信)級別)。 – 2010-06-30 08:01:30

回答

0

由於Tahbaza建議,這是一個相當簡單的觸發,

create trigger DataInstance_Trigger 
    On DataInstance 
After update 
as 
Begin 
    Update 
     DataInstance 
    Set 
     DataInstance.IsCurrent = 0 
    From DataInstance di, Inserted i 
    Inner join DataContainer dc on 
     i.DataContainerId = dc.ParentDataContainerId 
    Where di.DataContainerId = dc.DataContainerId 
      di.IsCurrent = 1