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

时间:2014-01-20 02:26:14

标签: 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语句之前或之后关闭和取消分配游标吗?
  5. 示例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;
    

1 个答案:

答案 0 :(得分:3)

我会在BEGIN TRY之前声明并打开光标,然后在END CATCH之后关闭并取消分配,以尽量减少您在交易中花费的时间。这也意味着您不需要两次编写close / deallocate语句。

我的第二选择是声明并打开BEGIN TRANSACTION内的光标,然后在ROLLBACK之前关闭并取消分配。我相信其他人会喜欢这种风格。

这些方式游标完全在try / catch和transaction之外,或完全包含在其中。这样做也感觉就像跨越范围给我,但肯定还会有用。我认为这个问题主要是风格问题

相关问题