SQL для цикла с использованием идентификаторов, возвращаемых в операторе Select

Мне нужно удалить кучу строк из моей базы данных при определенном условии. У меня есть оператор выбора, чтобы вернуть это условие, а затем для каждой строки в этом операторе выбора мне нужно выполнить SP, который удалит эти строки и загрузку связанных строк. Пока у меня есть:

select importfileid from import.importfiles where importfilestatusid < 7

а затем выполнить

EXEC    [import].[spDeleteFromAllImportRelatedTables]
    @fileID = @importfileid

Я просто не уверен, как сделать между ними? Если бы кто-то мог указать мне в правильном направлении, это было бы здорово.

NB: Это одноразовая вещь. Производительность не проблема.


person ediblecode    schedule 05.01.2012    source источник


Ответы (5)


вы можете использовать курсор:

declare @importFileID int
declare @cur cursor

set @cur = cursor fast_forward for 
select importfileid from import.importfiles where importfilestatusid < 7

open @cur
fetch next from @cur into @importFileID
while(@@fetch_status = 0)
begin
  exec [import].[spDeleteFromAllImportRelatedTables] @fileID = @importFileID
  fetch next from @cur into @importFileID
end
close @cur
deallocate @cur
person Matten    schedule 05.01.2012
comment
Спасибо, это было идеально. Я не знал о курсорах и, вероятно, выбирал бы каждый раз, когда удалял их. Я должен буду прочитать в них. NB: = не ==. +1 - person ediblecode; 05.01.2012
comment
конечно, =, а не ==, я всегда забываю об этом, если не использую sql в течение короткого времени :) - person Matten; 05.01.2012

Попробуйте использовать курсор на select . Посмотрите по этой ссылке http://msdn.microsoft.com/en-us/library/ms180169.aspx

person ikirachen    schedule 05.01.2012

Я никогда не буду предлагать использовать курсор, скорее используйте подход, основанный на SET. если возможно, вы можете использовать соединения для всех относительных таблиц, чтобы удалить все эти строки. Это был бы более быстрый подход. Создайте один SP и создайте одно задание, которое сделает это за вас с определенным интервалом, и жизнь будет легкой.

person Nilesh Thakkar    schedule 05.01.2012
comment
поскольку оператор просто хочет делать это один раз или время от времени, курсор снова ничего не говорит, так как быстро не очень важно... - person Matten; 05.01.2012
comment
@ Маттен, ты прав, но я просто делюсь своей точкой зрения на решение проблемы. Я должен был сказать по-другому, без обид. - person Nilesh Thakkar; 05.01.2012
comment
Я полностью согласен с вами, операции на основе наборов всегда (величины) быстрее, чем операции, основанные на процедурном программировании в t-sql. - person Matten; 05.01.2012

У вас есть несколько вариантов, ни один из которых не является красивым.

Используйте курсор

С помощью курсора (fastforward readonly) вы можете просмотреть результаты по одному за раз и вызвать хранимую процедуру.


Удержание стола

Вставьте все записи в таблицу, затем запишите хранимую процедуру для чтения из этой таблицы.

Это может быть реальная таблица или #temporary_table.

Преимущество этого в том, что вы можете выполнять все удаления вместе, а не в итеративном цикле.


Инкапсулировать первый шаг в функции

Если вы поместите свой код SELECT в функцию, вы можете перекодировать SP для вызова этой функции, чтобы найти записи, которые нужно удалить. Тогда параметры SP становятся такими же, как и параметры функции.


В SQL Server 2008+ с табличными параметрами это несколько прибрано. Но не в SQL Server 2005.

person MatBailie    schedule 05.01.2012

Я предполагаю, что SP делает что-то более особенное, чем просто удаление строки.

Если это разовая вещь, не могли бы вы просто сделать что-то хакерское, например:

SELECT 'EXEC    [import].[spDeleteFromAllImportRelatedTables]    @fileID =',  importfileid from import.importfiles where importfilestatusid < 7

А потом скопировать и вставить результаты и запустить?

В качестве альтернативы, если это запланированная очистка, подумайте о том, чтобы переосмыслить свой код и написать новый SP, который делает то же, что и DeleteFromAllImportRelatedTables, но с использованием критериев, указанных выше. Хотя может быть некоторое дублирование кода, это, вероятно, ускорит и упростит понимание того, что происходит, и упростит отладку, поскольку вы не будете отслеживать вызовы SP внутри SP, чтобы найти какие-либо проблемы.

person Richard Hanley    schedule 05.01.2012