如何避免在动态sql更新中使用游标?

时间:2014-10-27 15:49:20

标签: sql-server tsql dynamic-sql

因此,我尝试重写我们用来使用更好的基于集合的逻辑的一些存储过程,并减少或消除由于性能问题而使用的游标。但是,我无法在不使用游标的情况下提出更有效的方法来执行以下操作。

目前,我正在做的是基本上将初始结果集选择到类似

的临时表中
INSERT INTO #tmptable
SELECT stuff.id
    ,stuff.datapoint
    ,stuff.database
    ,'' AS missingdata
FROM STUFF

通常返回250-500行信息​​。 ''''是一个数据点,它位于数百个其他数据库中的任何一个中 - 其名称由stuff.database指定。尽管存在数百种可能的选项,但每个结果集中通常只有三个或四个唯一数据库。因此,我目前正在做的是:

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

由于每个结果集中通常只需要少量数据库,因此光标只需循环几次,性能影响不大。尽管如此,我还是不喜欢使用它们,并且觉得必须有一种更有效的方法来实现这一点。有什么想法吗?

1 个答案:

答案 0 :(得分: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