在事务内部或外部打开和关闭游标,以及在事务失败时如何关闭游标

Hyd*_*per 5 sql transactions cursor sql-server-2012

我正在SQL Server 2012中编写一个存储过程,该过程使用游标读取并在TRY CATCH块内进行事务。基本上,我的问题如下:

  1. 我应该在TRY CATCH块内声明光标吗?如果是,我应该在声明之前还是之后声明游标BEGIN TRANSACTION
  2. 我应该在BEGIN TRANSACTION语句之前还是之后打开游标?
  3. 我应该在COMMIT TRANSACTION语句之前还是之后关闭并释放游标吗?
  4. 如果出现ROLLBACK TRANSACTION故障,我应该在语句之前或之后关闭并释放游标吗?

示例T-SQL代码:

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;
Run Code Online (Sandbox Code Playgroud)

Ben*_*ers 5

我会在 之前声明并打开游标,然后在BEGIN TRY之后关闭并释放它,END CATCH以最大限度地减少您在事务中花费的时间。这也意味着您不需要两次编写 close/deallocate 语句。

我的第二个选择是BEGIN TRANSACTIONROLLBACK. 我相信其他人会更喜欢这种风格。

这些方式游标要么完全在 try/catch 和事务之外,要么完全包含在其中。否则对我来说感觉就像跨越了范围,但肯定仍然有效。我觉得这个问题主要是风格问题