SQL for цикъл, използващ идентификатори, върнати в израза Select

Трябва да изтрия куп редове от моята база данни при определено условие. Имам оператора select, за да върна това условие и след това за всеки ред в този оператор 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

Опитайте да използвате курсора върху избраното. Погледнете тази връзка 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
@Matten, ти си прав, но аз просто споделям моята гледна точка, за да реша проблема. Трябваше да кажа по друг начин, без да се обиждаш. - person Nilesh Thakkar; 05.01.2012
comment
Напълно съм съгласен с вас, базираните на множество операции винаги са (величини) по-бързи от тези, разчитащи на процедурно програмиране в t-sql. - person Matten; 05.01.2012

Имате няколко възможности, нито една от които не е красива.

Използване на курсор

С курсор (само за четене напред) вие преглеждате резултатите един по един и извиквате съхранената процедура.


Поддържаща маса

Вмъкнете всички записи в таблица, след което запишете съхранената процедура за четене от тази таблица.

Това може да бъде истинска таблица или #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