4

質問があります。私はカーソルに取り組んでいます。毎回、最後のレコードをフェッチしてそのデータを出力した後、カーソルは追加の行を出力します。私が言いたいことを理解するために、次のサンプル例を考えてみてください: 10 人の顧客だけに関する情報を印刷したいです。

USE Northwind
GO

DECLARE myCursor CURSOR 
FOR SELECT TOP(10) ContactName FROM Customers
DECLARE @RowNo int,@ContactName nvarchar(30)
SET @RowNo=1
OPEN myCursor
FETCH NEXT FROM myCursor INTO @ContactName
PRINT  LEFT(CAST(@rowNo as varchar) + '      ',6)+'  '+ @ContactName
SET @RowNo=@RowNo+1
SET @ContactName=''
WHILE @@FETCH_STATUS=0
  BEGIN
        FETCH NEXT FROM myCursor INTO @ContactName
        PRINT + LEFT(CAST(@rowNo as varchar) + '      ',6)+'  '+ @ContactName
        SET @RowNo=@RowNo+1
        SET @ContactName=''
  END
CLOSE myCursor
DEALLOCATE myCursor

次に、出力を見てください。

1       Maria Anders
2       Ana Trujillo
3       Antonio Moreno
4       Thomas Hardy
5       Christina Berglund
6       Hanna Moos
7       Frédérique Citeaux
8       Martín Sommer
9       Laurence Lebihan
10      Elizabeth Lincoln
11      

行番号 11 も印刷されています。カーソルの問題ですか、それとも常に発生しますか? この追加データを印刷しない方法はありますか?ありがとうございます (私は sql erver 2008 を使用しています)

4

5 に答える 5

5

また...

FETCH NEXT FROM myCursor INTO @ContactName
WHILE @@FETCH_STATUS = 0
BEGIN
    -- do stuff

    FETCH NEXT FROM myCursor INTO @ContactName
END

または...

WHILE @@FETCH_STATUS = 0
BEGIN
    FETCH NEXT FROM myCursor INTO @ContactName
    IF @@FETCH_STATUS = 0
    BEGIN
        -- do stuff
    END
END

または...

WHILE (1 = 1)
BEGIN
    FETCH NEXT FROM myCursor INTO @ContactName
    IF @@FETCH_STATUS <> 0
        BREAK

    -- do stuff
END
于 2010-08-31T12:26:45.720 に答える
3

SQL Server 2008 を使用しているとのことでした。SQL Server 2005 以降では、必要なことを行うためにカーソルはまったく必要ありません。

select top 10 left(cast(row_number() over(order by ContactName) as varchar)+ '      ', 6) + ContactName
    from Customers
于 2010-08-31T13:39:39.557 に答える
1

印刷ロジックがどのように複製されているかがわかりますか? これは、何が問題なのかを示すポインタです。ループは次のようになります。

FETCH NEXT INTO @working_variables
WHILE @@FETCH_STATUS = 0
    -- process @working_variables
    FETCH NEXT INTO @working_variables

唯一の複製されたコードはそれ自体であるべきFETCH NEXTです - あなたが今持っている方法では、最後FETCHが起こりますが、終了PRINTするWHILEことができます。

于 2010-08-31T12:26:45.020 に答える
0

レコード セットの最後の FETCH は、@@FETCH_STATUS を 0 以外に設定します。

FETCH NEXT コマンドは、WHILE BLOCK の最後の行にする必要があります。

USE Northwind
GO

DECLARE myCursor CURSOR 
FOR SELECT TOP(10) ContactName FROM Customers
DECLARE @RowNo int,@ContactName nvarchar(30)
SET @RowNo=0
OPEN myCursor
FETCH NEXT FROM myCursor INTO @ContactName
WHILE @@FETCH_STATUS=0
  BEGIN

        SET @RowNo=@RowNo+1
        SET @ContactName=''
        PRINT + LEFT(CAST(@rowNo as varchar) + '      ',6)+'  '+ @ContactName
        FETCH NEXT FROM myCursor INTO @ContactName
  END
CLOSE myCursor
DEALLOCATE myCursor
于 2010-08-31T12:27:05.797 に答える
0

これはオフバイワン エラーです。コードの重複を少なくして、カーソルを反復処理するより良い方法を次に示します。

USE Northwind
GO

DECLARE myCursor CURSOR 
FOR SELECT TOP(10) ContactName FROM Customers
DECLARE @RowNo int,@ContactName nvarchar(30)
SET @RowNo=0 -- initialize counters at zero, increment after the fetch/break
OPEN myCursor
WHILE 1=1 BEGIN -- start an infinite loop
  FETCH NEXT FROM myCursor INTO @ContactName
  IF @@FETCH_STATUS <> 0 BREAK
  SET @RowNo=@RowNo+1
  PRINT  LEFT(CAST(@rowNo as varchar) + '      ',6)+'  '+ @ContactName
END
CLOSE myCursor
DEALLOCATE myCursor

追加のポイントについては、カーソル変数を使用し、FAST_FORWARD および TYPE_WARNING で宣言するか、小さなデータセットの場合は STATIC を宣言します。例えば:

DECLARE @cursor CURSOR
SET @cursor = CURSOR FAST_FORWARD TYPE_WARNING FOR
  SELECT TOP (10) ContactName FROM Customers
OPEN @cursor 
......
CLOSE @cursor
DEALLOCATE @cursor

CLOSE と DEALLOCATE は厳密には必要ありません。バッチの最後でカーソル変数が範囲外になるためです。ただし、後でコードを最後に追加する可能性があり、できるだけ早くリソースを解放する必要があるため、これはまだ良い形式です。

TYPE_WARNING は、要求された型が SELECT ステートメントと互換性がない場合、SQL Server が要求されたカーソル型 (FAST_FORWARD) を別の型 (通常は STATIC) に暗黙的に変換するタイミングを示します。

于 2010-08-31T13:32:12.773 に答える