2014-10-27 1 views
2

Итак, я пытаюсь переписать некоторые из хранимых процедур, которые мы используем, чтобы использовать лучшую логику на основе набора и уменьшить или исключить использование курсоров из-за проблем с производительностью. Однако я не могу придумать более эффективный способ сделать это, не прибегая к использованию курсора.Как избежать использования курсора в динамическом обновлении sql?

В настоящее время, что я делаю, в основном выбирая начальный набор результатов во временную таблицу, которая выглядит как

INSERT INTO #tmptable 
SELECT stuff.id 
    ,stuff.datapoint 
    ,stuff.database 
    ,'' AS missingdata 
FROM STUFF 

который обычно возвращается в любом из 250-500 строк информации. «'- это дататаунтон, который находится в любой из нескольких сотен других баз данных, имя которой указано в базе данных. Несмотря на наличие сотен возможных вариантов, в каждом результирующем наборе обычно всего три или четыре уникальных баз данных. В результате то, что я сейчас делаю это:

DECLARE @dbname VARCHAR(255) 
DECLARE a_cursor CURSOR LOCAL 
FOR 
SELECT DISTINCT database 
FROM #tmptable 

OPEN a_cursor 

FETCH NEXT 
FROM a_cursor 
INTO @dbname 

WHILE @@FETCH_STATUS = 0 
BEGIN 
    SET @SQL = 'UPDATE #tmptable 
       SET missingdata = bin.dataaggregate 
       FROM ((SELECT pd.id id 
       ,STUFF((SELECT '','' + pdd.bin 
        FROM server.[' + @dbname + '].dbo.proddetails pdd 
        WHERE pdd.id= pd.id 
        GROUP BY pdd.id, pdd.bin 
        FOR XML PATH(''''), TYPE).value(''.'', ''VARCHAR(max)''), 1, 1, '''') dataaggregate 
       FROM server.[' + @dbname + '].dbo.proddetails pd) bin 
       INNER JOIN #tmptable tir ON tir.id= bin.id 
EXEC sp_executesql @SQL 

FETCH NEXT 
FROM a_cursor 
INTO @dbname 
END 

CLOSE a_cursor 

DEALLOCATE a_cursor 

Поскольку, как правило, лишь несколько баз данных, необходимых в каждом наборе результатов, курсор должен петлю лишь несколько раз, а производительность хит ISN» t ужасно. Тем не менее, я не люблю их использовать и чувствую, что должен быть более эффективный способ сделать это. Есть идеи?

ответ

0

Используется:

INSERT INTO #tmptable 
SELECT stuff.id 
    ,stuff.datapoint 
    ,stuff.[database] 
    ,'' AS missingdata 
    ,row_number() over (order by stuff.id) as rn 
FROM STUFF 

declare @i int= 1; 
declare @max int = (select max(rn) from #tmptable) 
while @i <= @max 
begin 
    declare @dbname sysname 
    select @dbname = [database] from #tmptable where rn = @i 

    --exec your dynamic sql hear 
    set @i +=1 
end 
+0

Не будет ли это вызвать динамический SQL будет выполняться в 300 раз (то есть, один раз для каждой строки), а не три или четыре казни варианты курсора? – rheinz

+2

[Итак, вы думаете, что вы удалили курсор, не так ли?] (Http://sqlblog.com/blogs/aaron_bertrand/archive/2012/01/26/the-fallacy-that-a-while-loop-isn- ta-cursor.aspx) –

+0

курсор и while цикл это не то же самое! Поэтому вы спрашиваете «как избежать использования курсора», на мой вопрос ответит на ваш вопрос. –

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