11

T-SQL では、カーソルからの結果を反復する場合、ループのFETCH前にステートメントを繰り返すのが一般的な方法のようです。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;2 回表示されることに注意してください。)

変数の長いリストを選択FETCHすると、見苦しく、もちろん「非 DRY」コードである大きな重複ステートメントができます。

私は事後条件のフロー制御 T-SQL ステートメントを認識していないので、WHILE(TRUE)and then BREAKwhen @@FETCH_STATUSis not zero に頼る必要があるようです。これは私には不格好に感じます。

他にどのようなオプションがありますか?

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ものは、Fetch nextではなく、ただのfetch

その後、あなたは自分自身を繰り返していません。

私はカーソルを取り除くためにより多くの努力を費やし、DRYの教義にはあまり力を入れませんでした(しかし、それが本当に重要な場合は、GOTO:)を使用できます-申し訳ありませんが、M。ダイクストラ)

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

Dry:
    FETCH NEXT FROM Employee_Cursor; 
END; 
于 2012-09-04T10:31:12.623 に答える
-2

カーソルがレコードセットの現在の行へのポインタであることは明らかです。しかし、それが使用できない限り、単なるポインティングは意味がありません。Fetchステートメントが登場します。これにより、レコードセットからデータが取得され、指定された変数に格納されます。したがって、最初のフェッチステートメントを削除すると、操作用の「FETCHED」レコードがないため、whileループは機能しません。最後のフェッチステートメントを削除すると、「while」はループスルーしません。

したがって、完全なレコードセットをループスルーするには、両方のフェッチステートメントが必要です。

于 2012-09-04T11:16:09.990 に答える
-4

簡単に言うと、できません...それがSQLのステートメントが機能するほとんどの場所です。ループの前の最初の行を取得してから、whileステートメントで再度実行する必要があります。

カーソルを取り除き、カーソルなしでクエリを解決する方法についてのより良い質問。

于 2012-09-04T10:34:14.223 に答える