SQL Server游标 vs WHILE循环

huangapple go评论57阅读模式
英文:

SQL Server Cursor vs WHILE loop

问题

在SQL Server中,当你需要循环处理一组数据时,是否使用SQL Server游标有好处?还是只是使用WHILE循环(见下文)一样好。

这假设你想要执行一些无法以集合方式完成的操作。

我问这个问题是因为WHILE循环似乎更清晰、更容易理解。

-- 遍历一个表
DROP TABLE IF EXISTS #LoopingSet;
CREATE TABLE #LoopingSet (RowID INT IDENTITY(1,1), DatabaseName sysname);
INSERT INTO #LoopingSet (DatabaseName) SELECT [name] FROM sys.databases WHERE database_id > 4 ORDER BY name;

DECLARE @i INT = (SELECT MIN(RowID) FROM #LoopingSet);
DECLARE @n INT = (SELECT MAX(RowID) FROM #LoopingSet);
DECLARE @DatabaseName sysname = '';

WHILE (@i <= @n)
BEGIN
    SELECT @DatabaseName = DatabaseName FROM #LoopingSet WHERE RowID = @i;
    PRINT @DatabaseName; -- 在这里执行一些操作
    SELECT @i = MIN(RowID) FROM #LoopingSet WHERE RowID > @i;
END;
英文:

In SQL Server: when you need to loop a set of data, is there a benefit of using a SQL Server cursor. Or is using a WHILE loop (see below) just the same.

This assumes that you want to do something that cannot be done in a set-based way

I ask because the WHILE loop seems clearer and easier to understand.

-- loop through a table
DROP TABLE IF EXISTS #LoopingSet;
CREATE TABLE #LoopingSet (RowID INT IDENTITY(1,1), DatabaseName sysname);
INSERT INTO #LoopingSet (DatabaseName) SELECT [name] FROM sys.databases WHERE database_id &gt; 4 ORDER BY name;

DECLARE @i INT = (SELECT MIN(RowID) FROM #LoopingSet);
DECLARE @n INT = (SELECT MAX(RowID) FROM #LoopingSet);
DECLARE @DatabaseName sysname = &#39;&#39;;

WHILE (@i &lt;= @n)
BEGIN
    SELECT @DatabaseName = DatabaseName FROM #LoopingSet WHERE RowID = @i;
    PRINT @DatabaseName; -- do something here
    SELECT @i = MIN(RowID) FROM #LoopingSet WHERE RowID &gt; @i;
END;

答案1

得分: 2

I ask because the WHILE loop seems clearer and easier to understand.

这是因为 WHILE 循环似乎更清晰和更容易理解。

英文:

> I ask because the WHILE loop seems clearer and easier to understand.

Is it clearer and easier to understand?

DECLARE 
    @Name sysname,
    @Names CURSOR,
    @Rows integer;

SET @Names = CURSOR FORWARD_ONLY STATIC READ_ONLY FOR
    SELECT [name] 
    FROM sys.databases 
    WHERE database_id &gt; 4 
    ORDER BY [name] ASC;

OPEN @Names;

SET @Rows = @@CURSOR_ROWS;

WHILE @Rows &gt; 0
BEGIN
    FETCH NEXT FROM @Names INTO @Name;
    PRINT @Name;
    SET @Rows -= 1;
END;

It's a subjective question but objectively, your implementation of a cursor is a little less efficient than using the built-in facility.

huangapple
  • 本文由 发表于 2023年6月29日 19:41:26
  • 转载请务必保留本文链接:https://go.coder-hub.com/76580692.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定