为什么选择顶级查询和临时表而不是循环游标?

Jac*_*cob 6 sql-server t-sql cursors

当谈到在 T-SQL 中循环遍历大量数据时,我在 Internet 上看到的大多数示例都使用这样的模式:

declare @someVariable int
declare @remainingRows int

select someColumn from someTables into #someTempTable

select @remainingRows = count(*) from #someTempTable
while @remainingRows > 0 begin

    select top 1 @someVariable = someColumn from #someTempTable

    -- Do stuff

    delete top 1 from #someTempTable

    select @remainingRows = count(*) from #someTempTable
end
Run Code Online (Sandbox Code Playgroud)

这似乎比使用这样的游标的示例更常见:

declare @someVariable int

select someColumn from someTables into #someTempTable

declare @someCursor cursor for select someColumn from #someTempTable
open @someCursor
fetch next @someVariable from @someCursor

while @@fetch_status = 0 begin

    -- Do stuff

    fetch next @someVariable from @someCursor
end

close @someCursor
Run Code Online (Sandbox Code Playgroud)

我有时会听到提到性能原因,但对我来说这是违反直觉的;迭代一组数据的只进只读游标不会比不断查询和更新临时表更有效吗?我明白,如果它是一个游标迭代一个表的表可能被锁定更新的错误选项,但是一个非共享临时表上的游标不会有这个问题,是吗?

奖金问题;如果游标没问题,那么使用快照隔离的常规查询上的游标是否安全,这样我就可以避免手动创建临时表的烦恼,即:

DECLARE @someCursor CURSOR LOCAL FORWARD_ONLY STATIC READ_ONLY FOR 
SELECT something
FROM tables
Run Code Online (Sandbox Code Playgroud)

RLF*_*RLF 10

不,循环不一定比游标快,尽管有些人更习惯使用它们。我自己曾经经历过循环写作阶段。游标也有多种风格,因此选择正确类型的游标是一个重要的细节。

您的问题可能由 Aaron Bertrand(从 2012 年开始)回答,因为他进行了几次比较测试,网址为:

简而言之,他发现正确的游标比几个循环结构的运行速度要快得多。

通读他的比较应该会帮助您对游标感到满意。

但只有在需要它们的时候。