2010-06-30 2 views
0

У меня есть очень общий набор из трех таблиц, в которых хранятся все мои данные, которая работает блестяще (речь идет небольшое количество данных здесь)SQL Server: рекурсивная хранимая процедура

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 (как я получаю сообщение об ошибке, что курсор уже открыт), так что это СП будет работать только один уровень.

Есть ли более хитрый способ сделать это?

+0

Хранение всех данных в одной таблице, а затем, используя курсоры для обработки ваших записей практики, которые вы должны получить от , Вы просите головную боль, когда игнорируете мудрость нормализации ваших данных и силу установленной логики, для которой был разработан SQL ... Возможно, вам стоит подумать о рефакторинге для вашей собственной пользы позже? – Tahbaza

+1

Поскольку я ненавижу палочки в грязи, которые просто публикуют отрицательные замечания, а затем уходят, вот одно решение вашей проблемы, если вы решите вспахать вперед: используйте язык программирования приложений вне SQL для выполнения рекурсии. Они обычно не ограничены правилами рекурсивных вызовов, и вы можете легче обрабатывать записи с помощью набора записей или эквивалента, если вы предпочитаете логику строки. Счастливое кодирование ... – Tahbaza

+0

Я должен согласиться с Tahbaza, но если вы настаиваете на этом маршруте, я бы использовал триггер. Триггеры могут выполняться рекурсивно (до определенного (настраиваемого уровня)). –

ответ

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 

Конец

Смежные вопросы