11

FETCH在 T-SQL 中,当从游标迭代结果时,在循环之前重复语句似乎是一种常见的做法WHILE。以下来自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

(注意如何FETCH NEXT FROM Employee_Cursor;出现两次。)

如果FETCH选择一长串变量,那么我们有一个大的重复语句,它既丑陋,当然也是“非 DRY”代码。

我不知道后置条件控制流 T-SQL 语句,所以看来我不得不求助于 aWHILE(TRUE)然后BREAKwhen@@FETCH_STATUS不为零。这对我来说感觉很笨拙。

我还有什么其他选择?

4

6 回答 6

16

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
于 2013-09-26T14:01:23.283 回答
9

这就是我所采取的(哦,真可惜):

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

你可以看到我为什么发布一个问题。我不喜欢if应该在while.

于 2012-09-04T10:53:31.953 回答
4

第一个Fetch不应该是 a Fetch next,只是 a fetch

那你不是在重复自己。

我会花更多的精力来摆脱光标,而不是在 DRY 教条上,(但如果它真的很重要,你可以使用GOTO:) - 对不起,M. Dijkstra)

GOTO Dry
WHILE @@FETCH_STATUS = 0 
BEGIN 
    --- stuff here

Dry:
    FETCH NEXT FROM Employee_Cursor; 
END; 
于 2012-09-04T10:31:12.623 回答
0

这是我的微薄贡献。单个 FETCH 语句,没有 GOTO,没有 BREAK,没有 CONTINUE。

-- Sample table
DROP TABLE IF EXISTS #tblEmployee;
CREATE TABLE #tblEmployee(ID int, Title varchar(100));
INSERT INTO #tblEmployee VALUES (1, 'First One'), (2, 'Second Two'), (3, 'Third Three'), (3, '4th Four');
-- Cursor with one FETCH statement
DECLARE @bEOF bit=0, @sTitle varchar(200), @nID int;
DECLARE cur CURSOR LOCAL FOR SELECT ID, Title FROM #tblEmployee;
OPEN cur;
WHILE @bEOF=0
BEGIN
    FETCH NEXT FROM cur INTO @nID, @sTitle;
    IF @@FETCH_STATUS<>0
        SET @bEOF=1;
    ELSE
    BEGIN
        PRINT Str(@nID)+'. '+@sTitle;
    END;
END;
CLOSE cur;
DEALLOCATE cur;
-- Cleanup
DROP TABLE IF EXISTS #tblEmployee;
于 2020-10-14T21:15:28.377 回答
-2

很明显,游标是指向记录集中当前行的指针。但是,除非可以使用,否则仅仅指向是没有意义的。这里出现了 Fetch 语句。这从记录集中获取数据,将其存储在提供的变量中。因此,如果您删除第一个 fetch 语句,while 循环将不起作用,因为没有“FETCHED”记录进行操作,如果您删除最后一个 fetch 语句,“while”将不会循环。

因此,有必要让这两个 fetch 语句循环通过完整的记录集。

于 2012-09-04T11:16:09.990 回答
-4

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

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

于 2012-09-04T10:34:14.223 回答