【问题标题】:How to avoid cursor use in dynamic sql update?如何避免在动态 sql 更新中使用游标?
【发布时间】:2014-12-22 20:39:37
【问题描述】:

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

目前,我正在做的基本上是选择一个初始结果集到一个看起来像这样的临时表中

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

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

【问题讨论】:

    标签: sql-server tsql dynamic-sql


    【解决方案1】:

    使用这个:

    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
    

    【讨论】:

    • 这样会不会导致动态sql被执行300次(即每行一次)而不是游标变体的三四次执行?
    • 游标和while循环不一样想!所以你问“如何避免使用光标”,我的帖子就你的问题得到了回答。
    • 逐行是逐行,不管是显式游标还是隐式游标。 Did you read the link?
    猜你喜欢
    • 2010-09-06
    • 1970-01-01
    • 1970-01-01
    • 2011-12-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多