使用游标时如何避免T-SQL中重复的​​FETCH?

Ber*_*ann 10 sql t-sql sql-server

在T-SQL中,当从游标迭代结果时,通常的做法是FETCHWHILE循环之前重复该语句.以下来自Microsoft的示例:

DECLARE Employee_Cursor CURSOR FOR
SELECT EmployeeID, Title FROM AdventureWorks2012.HumanResources.Employee
    WHERE JobTitle = 'Marketing Specialist';
OPEN Employee_Cursor;

FETCH NEXT FROM Employee_Cursor;
WHILE @@FETCH_STATUS = 0
    BEGIN
        FETCH NEXT FROM Employee_Cursor;
    END;
CLOSE Employee_Cursor;
DEALLOCATE Employee_Cursor;
GO
Run Code Online (Sandbox Code Playgroud)

(请注意FETCH NEXT FROM Employee_Cursor;两次出现的情况.)

如果FETCH选择一个很长的变量列表,那么我们有一个大的重复语句既丑陋又当然是"非DRY"代码.

我不知道后置条件控制流T-SQL语句所以我似乎不得不求助于a WHILE(TRUE)然后BREAK何时@@FETCH_STATUS不为零.这对我来说很笨拙.

我还有其他选择吗?

Vin*_*ren 12

Chris Oldwood在网上发布了一个很好的结构,非常优雅:

DECLARE @done bit = 0 

WHILE (@done = 0)  
BEGIN 
  -- Get the next author.  
  FETCH NEXT FROM authors_cursor  
  INTO @au_id, @au_fname, @au_lname  

  IF (@@FETCH_STATUS <> 0) 
  BEGIN 
    SET @done = 1 
    CONTINUE 
  END 

  -- 
  -- stuff done here with inner cursor elided 
  -- 
END
Run Code Online (Sandbox Code Playgroud)


Ber*_*ann 8

这就是我所使用的(哦,它的耻辱):

WHILE (1=1)
BEGIN
    FETCH NEXT FROM C1 INTO
   @foo,
   @bar,
   @bufar,
   @fubar,
   @bah,
   @fu,
   @foobar,
   @another,
   @column,
   @in,
   @the,
   @long,
   @list,
   @of,
   @variables,
   @used,
   @to,
   @retrieve,
   @all,
   @values,
   @for,
   @conversion

    IF (@@FETCH_STATUS <> 0)
    BEGIN
        BREAK
    END

     -- Use the variables here
END

CLOSE C1
DEALLOCATE C1
Run Code Online (Sandbox Code Playgroud)

你可以看到我发布问题的原因.我不喜欢流程控制如何隐藏在if语句中while.

  • 我认为,从技术上讲,这应该是公认的答案,因为它确实避免重复`FETCH`语句. (3认同)

Fed*_*jdu -4

简单地说你不能...这就是 SQL 中大多数 where 语句的工作方式。您需要在循环之前获取第一行,然后在 while 语句中再次执行此操作。

更好的问题是如何摆脱光标并尝试在没有光标的情况下解决您的查询。