我在SQL Server 2012中编写了一个存储过程,它使用游标进行读取,并在TRY CATCH
块内部进行事务处理。基本上,我的问题如下:
TRY CATCH
块内声明我的光标吗?如果是,我应该在BEGIN TRANSACTION
声明之前或之后声明光标吗?BEGIN TRANSACTION
声明之前或之后打开光标吗?COMMIT TRANSACTION
声明之前还是之后关闭并取消分配光标?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;
答案 0 :(得分:3)
我会在BEGIN TRY
之前声明并打开光标,然后在END CATCH
之后关闭并取消分配,以尽量减少您在交易中花费的时间。这也意味着您不需要两次编写close / deallocate语句。
我的第二选择是声明并打开BEGIN TRANSACTION
内的光标,然后在ROLLBACK
之前关闭并取消分配。我相信其他人会喜欢这种风格。
这些方式游标完全在try / catch和transaction之外,或完全包含在其中。这样做也感觉就像跨越范围给我,但肯定还会有用。我认为这个问题主要是风格问题