18

次のようなトリガーがあるとします。

CREATE TRIGGER trigger1
   ON [dbo].[table1] 
   AFTER UPDATE
AS 
BEGIN               
    --declare some vars
    DECLARE @Col1 SMALLINT 
    DECLARE @Col1 TINYINT 

    --declare cursor        
    DECLARE Cursor1 CURSOR FOR 
    SELECT Col1, Col2 FROM INSERTED             

    --do the job
    OPEN Cursor1
    FETCH NEXT FROM Cursor1 INTO @Col1, @Col2

    WHILE @@FETCH_STATUS = 0
    BEGIN
        IF ...something...
        BEGIN           
            EXEC myProc1 @param1 = @Col1, @Param2 = @Col2
        END             
        ELSE
        IF ...something else...
        BEGIN           
            EXEC myProc2 @param1 = @Col1, @Param2 = @Col2
        END     

        FETCH NEXT FROM Cursor1 INTO @Col1, @Col2               
    END

    --clean it up       
    CLOSE Cursor1
    DEALLOCATE Cursor1                  
END

Cursor1 が常に閉じられ、割り当てが解除されていることを確認したいと思います。myProc1 または myProc2 でさえ失敗します。

try/catch ブロックを使用しますか?

4

4 に答える 4

41

CURSOR_STATUS() 関数を使用できます。

if CURSOR_STATUS('global','cursor_name') >= 0 
begin
 close cursor_name
  deallocate cursor_name 
end

参照: http://msdn.microsoft.com/en-us/library/ms177609.aspx

于 2010-01-20T20:20:34.697 に答える
17

はい、TRY/CATCH を使用しますが、後で割り当て解除などを行ってください。残念ながら、SQL Server には finally はありません。

ただし、これを別の try/catch でラップすることをお勧めします

CREATE TRIGGER trigger1 ON [dbo].[table1] AFTER UPDATE
AS 
BEGIN                           
    --declare some vars
    DECLARE @Col1 SMALLINT, @Col1 TINYINT 

    BEGIN TRY
        --declare cursor            
        DECLARE Cursor1 CURSOR FOR 
        SELECT Col1, Col2 FROM INSERTED                     

        --do the job
        OPEN Cursor1
        FETCH NEXT FROM Cursor1 INTO @Col1, @Col2

        WHILE @@FETCH_STATUS = 0
        BEGIN
            IF ...something...
                    EXEC myProc1 @param1 = @Col1, @Param2 = @Col2
            ELSE
            IF ...something else...
                    EXEC myProc2 @param1 = @Col1, @Param2 = @Col2

            FETCH NEXT FROM Cursor1 INTO @Col1, @Col2                               
        END
    END TRY
    BEGIN CATCH
        --do what you have to
    END CATCH

    BEGIN TRY
        --clean it up               
        CLOSE Cursor1
        DEALLOCATE Cursor1                                  
    END TRY
    BEGIN CATCH
        --do nothing
    END CATCH
END

トリガー内のカーソルが良いアイデアかどうかは別の問題です...

于 2009-09-15T05:28:34.160 に答える
1

あなたがすべきことは、トリガーでカーソルを決して使用しないことです。代わりに、正しいセットベースのコードを記述してください。誰かが 100,000 件の新しいレコードのテーブルにデータをインポートした場合、テーブルが何時間もロックされ、データベースが悲鳴を上げて停止することになります。トリガーでカーソルを使用することは、非常に不適切な方法です。

于 2009-09-11T13:18:13.517 に答える