2010-06-30 217 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