Open and Close Cursors Inside or Outside a Transaction and How to Close a Cursor if a Transaction Fails

こ雲淡風輕ζ 提交于 2019-12-06 03:55:51

问题


I am writing a stored procedure in SQL Server 2012 that uses a cursor for reading and a transaction inside a TRY CATCH block. Basically, my questions are as follows:

  1. Should I declare my cursor inside the TRY CATCH block? If yes, should I declare the cursor before or after the BEGIN TRANSACTION statement?
  2. Should I open the cursor before or after the BEGIN TRANSACTION statement?
  3. Should I close and deallocate the cursor before or after the COMMIT TRANSACTION statement?
  4. Should I close and deallocate the cursor before or after the ROLLBACK TRANSACTION statement if something fails?

Sample T-SQL Code:

DECLARE @ColumnID AS INT;
DECLARE @ColumnName AS VARCHAR(20);
DECLARE @ColumnValue AS FLOAT;

-- Should I declare my cursor inside the TRY CATCH block?
-- If yes, should I declare the cursor before or after the BEGIN TRANSACTION statement?

DECLARE myCursor CURSOR LOCAL FAST_FORWARD FOR
    SELECT
        a.ColumnID,
        a.ColumnName,
        a.ColumnValue

    FROM
        MyTable a;

BEGIN TRY

    -- Should I open the cursor before or after the BEGIN TRANSACTION statement?

    BEGIN TRANSACTION myTransaction;

    OPEN myCursor;

    FETCH NEXT FROM myCursor INTO @ColumnID, @ColumnName, @ColumnValue;

    WHILE @@FETCH_STATUS = 0 BEGIN

        IF (@ColumnName IS NULL) BEGIN

            UPDATE
                MyTable

            SET
                @ColumnValue = NULL

            WHERE
                ColumnID = @ColumnID;

        END;

        FETCH NEXT FROM myCursor INTO @ColumnID, @ColumnName, @ColumnValue;

    END;

    -- Should I close and deallocate the cursor before or after the COMMIT TRANSACTION statement?

    CLOSE myCursor;
    DEALLOCATE myCursor;

    COMMIT TRANSACTION myTransaction;

END TRY
BEGIN CATCH

    -- Should I close and deallocate the cursor before or after the ROLLBACK TRANSACTION statement:

    IF CURSOR_STATUS('local', 'myCursor') = 1 BEGIN

        CLOSE myCursor;
        DEALLOCATE myCursor;

    END;

    ROLLBACK TRANSACTION myTransaction;

END CATCH;

回答1:


I would declare and open the cursor before the BEGIN TRY and then close and deallocate it after the END CATCH to minimize the amount of time you're spending in the transaction. This also means you don't need to write the close/deallocate statements twice.

My second choice would be to declare and open the cursor inside the BEGIN TRANSACTION and then close and deallocate before the ROLLBACK. I'm sure others will prefer this style.

These ways the cursor is either entirely outside the try/catch and transaction or entirely contained within them. Doing it otherwise feels like crossing scopes to me, but would certainly still work. I think this question is mainly an issue of style



来源:https://stackoverflow.com/questions/21225324/open-and-close-cursors-inside-or-outside-a-transaction-and-how-to-close-a-cursor

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!