web-dev-qa-db-ja.com

CURSORの無限ループ

一時テーブルが不要になったときに、カーソルを使用して一時テーブルをクリーンアップしようとしています。一時テーブルの名前と識別子を含む小さなテーブルがあります。カーソルは無限ループに陥っていますが、その中で特定のステートメントを実行した場合のみです。 FETCHから値を出力するだけで、完全に機能します。これがコードです。

_DECLARE @id bigint;
DECLARE @table_name varchar(max);

DECLARE st CURSOR LOCAL FAST_FORWARD FOR 
SELECT ID, TableName FROM SearchTables WHERE CustomerID IS NULL

OPEN st
FETCH NEXT FROM st INTO @id, @table_name
WHILE @@FETCH_STATUS <> -1 
BEGIN   
    IF(OBJECT_ID(@table_name) IS NOT NULL) 
        EXEC('DROP TABLE ' + @table_name);

    UPDATE SearchTables SET Deleted=1 WHERE ID=@id;

    PRINT CAST(@id AS varchar(max)) + ' ' + @table_name;

    FETCH NEXT FROM st INTO @id, @table_name;
END 

CLOSE st
DEALLOCATE st
_

これらの行をコメントアウトすると

_    IF(OBJECT_ID(@table_name) IS NOT NULL) 
        EXEC('DROP TABLE ' + @table_name);

    UPDATE SearchTables SET Deleted=1 WHERE ID=@id;
_

PRINTは、すべてのIDとテーブル名を出力します。コメントしないと、クエリをキャンセルするまで、最初の行が何度も表示されます。また、IF行をEXEC('DROP TABLE IF EXISTS ' + @table_name)に変更してみましたが、それも機能しませんでした。

6
CB_Ron

おそらく、Deleted=1を設定してFAST_FORWARDカーソルで再度読み取るときに、行を移動しています。代わりにSTATICカーソルを使用してください。これにより、データのコピーが反復処理され、走査しているデータ構造の変更が回避されます。

DECLARE st CURSOR LOCAL STATIC FOR . . .

WHILE @@FETCH_STATUS = 0が必要です。これは、何かが正しくない限り続行することを意味します。

<> -1を使用すると、フェッチされた行が欠落していても、またはフェッチ操作を実行していなくても続行され、戻り値として-1を取得しない限り、その戻り値は 4戻り値@@FETCH_STATUSの場合。

 0  The FETCH statement was successful.
-1  The FETCH statement failed or the row was beyond the result set.
-2  The row fetched is missing.
-9  The cursor is not performing a fetch operation

9
scsimon