在什么标准上可以比较 While 循环和游标?[复制]

On what criteria can While loops and Cursors be compared? [duplicate]

提问人:J. Mini 提问时间:11/2/2023 更新时间:11/2/2023 访问量:57

问:

假设我有一个查询,它实际上必须是游标或 while 循环。用什么标准来判断应该使用哪个?

值得注意的是,不是这个问题的重复。我不是想问每个选项的优缺点是什么。我假设我已经知道这一点,我问的是当卡住时如何在两个选项之间做出决定。

sql-server t-sql while-loop 数据库游标

评论

2赞 Stu 11/2/2023
在我使用 SQL Server 的 25 年中,我想我可能使用过一次实际的游标;有时我需要为一系列参数执行一个过程或执行一些其他重复性任务,我总是使用 while 循环,除非您需要其更高级的功能,例如滚动或更新,否则拥有光标的开销和复杂性是没有意义的
0赞 Patrick Hurst 11/2/2023
SQL 是一种基于集合的语言。没有多少情况下,任何类型的循环都是解决挑战的最佳方法。
0赞 Dale K 11/2/2023
鉴于您知道利弊,那么这只是个人选择的问题......你希望人们告诉你什么?
0赞 Nick.Mc 11/2/2023
您需要使用 while 循环来遍历游标,因此不确定问题是什么。也许提供一些代码示例
0赞 siggemannen 11/2/2023
我会说光标 100%,但请确保您使用只读转发本地静态光标。虽然充其量只能模拟光标。while 的唯一原因是,如果您还插入到正在循环的表中,并且还想处理这些行。

答:

-1赞 Xedni 11/2/2023 #1

很大程度上取决于个人喜好,或者与您合作的其他开发人员是否对看到光标有本能反应。就我个人而言,我唯一使用游标的时间是当它可以替换必须声明一个带有 RID 的临时表时,在其中插入行,然后执行循环直到WHILE@RID <= @MaxRID

即便如此,我喜欢它们的主要原因是,使用光标编写代码片段来循环比存根表格更容易。

所以基本上,如果我有一个场景,我必须做如下的事情才能使用循环......WHILE

-- Table based approach
declare @loopTable table
(
    RID int identity(1,1),
    TableName nvarchar(128)
)

declare 
    @RID int,
    @MaxRID int,
    @TableName nvarchar(128)

insert into @LoopTable(TableName)
select name
from sys.tables

select 
    @RID = 1,
    @MaxRID = @@rowcount

while @RID <= @MaxRID
begin

    select @TableName = TableName
    from @loopTable
    where RID = @RID
    select 'Do something for ' + @TableName

    select @RID += 1
end

我可能会用...

-- Cursor based approach
declare @TableName nvarchar(128)
declare c cursor local fast_forward for
    select name
    from sys.tables
open c

fetch next from c into @TableName

while @@fetch_status = 0
begin

    select 'Do something for ' + @TableName
    
    fetch next from c into @TableName

end

deallocate c

仅此而已。但实际上,不要低估许多数据库开发人员对游标的厌恶程度。他们的逻辑很笨拙,很难理解为什么你需要一个光标才能被接受,而且滥用光标的方法比正确使用它们的方法要多得多,以至于我认识的大多数人都避开了它们。local fast_forward

如果您有疑问,我会尝试使用循环,因为即使在最好的情况下,它也会执行与游标相同的功能,并且可以立即被其他数据库开发人员识别。当然,除非你正在与一群更喜欢光标的人一起工作,在这种情况下,这就是你的答案。WHILElocal fast_forward

评论

0赞 Charlieface 11/2/2023
“即使在最好的情况下,它也会执行与本地fast_forward游标相同的功能”,只有当它位于索引查询上时。否则,它在经验上比游标更糟糕。 在大多数情况下,游标实际上与 a 的性能更好或相同。显然,两者都应该避免。STATIClocal fast_forwardwhile