我以前从未使用过Transaction,Commit和Rollback,现在我需要使用一个。我已经在网上查了一些例子,以确保我实际上正确地使用了这个,但我仍然不确定我是否编码正确。我希望有人可以审查并告诉我这是否正确。
基本上我有一个应用程序的2个数据库。一个是归档 - 意味着不再由用户操纵的数据将被移动到该DB。但是如果他们需要它,我会将所需的数据移回主数据库以供使用。我的存储过程如下:
CREATE PROCEDURE [dbo].[spReopenClosed]
(
@Return_Message VARCHAR(1024) = '' OUT,
@IID uniqueidentifier,
@OpenDate smalldatetime,
@ReopenedBy uniqueidentifier
)
AS
BEGIN
SET NOCOUNT ON;
/******************************
* Variable Declarations
*******************************/
DECLARE @ErrorCode int
/******************************
* Initialize Variables
*******************************/
SELECT @ErrorCode = @@ERROR
IF @ErrorCode = 0
BEGIN TRANSACTION
/****************************************************************************
* Step 1
* Copy the Closed from the Archive
****************************************************************************/
INSERT INTO OPS.dbo.SM_T_In
SELECT
FROM OPS_ARCHIVE.Archive.SM_T_In W
WHERE W.GUID = @IID
AND W.OpenDate = @OpenDate
IF @ErrorCode <> 0
BEGIN
-- Rollback the Transaction
ROLLBACK
RAISERROR ('Error in Copying from the archive', 16, 1)
RETURN
END
/****************************************************************************
* Step 2
* copy the notes
****************************************************************************/
INSERT INTO OPS.dbo.SM_T_Notes
SELECT
FROM OPS_ARCHIVE.Archive.SM_T_Notes W
WHERE W.GUID = @IID
IF @ErrorCode <> 0
BEGIN
-- Rollback the Transaction
ROLLBACK
RAISERROR ('Error in copying the notes', 16, 1)
RETURN
END
/****************************************************************************
* Step 3
* Delete the from the Archive - this will also delete the notes
****************************************************************************/
DELETE
FROM OPS_ARCHIVE.Archive.SM_T_In
WHERE OPS_ARCHIVE.Archive.SM_T_In.GUID = @IID
IF @ErrorCode <> 0
BEGIN
-- Rollback the Transaction
ROLLBACK
RAISERROR ('Error in deleting the items from the Archive', 16, 1)
RETURN
END
COMMIT
BEGIN
SELECT @ErrorCode = @@ERROR
IF @ErrorCode = 0
SELECT @Return_Message = 'All data was moved over'
END
/*************************************
* Get the Error Message for @@Error
*************************************/
IF @ErrorCode <> 0
BEGIN
SELECT @Return_Message = [Description] -- Return the SQL Server error
FROM master.dbo.SYSMESSAGES
WHERE error = @ErrorCode
END
/*************************************
* Return from the Stored Procedure
*************************************/
RETURN @ErrorCode -- =0 if success, <>0 if failure
END
我有两个插件可以从Archive数据库中移动2个表中的数据。如果这些插入成功,那么我将从Archive DB中删除数据。我很感激任何有关这方面的反馈,我需要确保我正确地做到这一点。
由于
答案 0 :(得分:31)
哦,我按照您的要求使用概念 TRY CATCH和TRANSACTION 快速重写您的SP,但我没有检查它。
此代码适用于 SQL 2005/2008
如果此反馈对您有用,请告诉我
CREATE PROCEDURE [dbo].[spReopenClosed]
(
@Return_Message VARCHAR(1024) = '' OUT,
@IID uniqueidentifier,
@OpenDate smalldatetime,
@ReopenedBy uniqueidentifier
)
AS
SET NOCOUNT ON;
/******************************
* Variable Declarations
*******************************/
DECLARE @ErrorCode int
DECLARE @ErrorStep varchar(200)
/******************************
* Initialize Variables
*******************************/
SELECT @ErrorCode = @@ERROR
BEGIN TRY
BEGIN TRAN
/****************************************************************************
* Step 1
* Copy the Closed from the Archive
****************************************************************************/
SELECT @ErrorStep = 'Error in Copying from the archive';
INSERT INTO OPS.dbo.SM_T_In
SELECT *
FROM OPS_ARCHIVE.Archive.SM_T_In
WHERE GUID = @IID
AND W.OpenDate = @OpenDate
/****************************************************************************
* Step 2
* copy the notes
****************************************************************************/
SELECT @ErrorStep = 'Error in copying the notes'
INSERT INTO OPS.dbo.SM_T_Notes
SELECT *
FROM OPS_ARCHIVE.Archive.SM_T_Notes
WHERE GUID = @IID
/****************************************************************************
* Step 3
* Delete the from the Archive - this will also delete the notes
****************************************************************************/
SELECT @ErrorStep = 'Error in deleting the items from the Archive'
DELETE
FROM OPS_ARCHIVE.Archive.SM_T_In
WHERE OPS_ARCHIVE.Archive.SM_T_In.GUID = @IID
COMMIT TRAN
SELECT @ErrorCode = 0, @Return_Message = 'All data was moved over'
/*************************************
* Return from the Stored Procedure
*************************************/
RETURN @ErrorCode -- =0 if success, <>0 if failure
END TRY
BEGIN CATCH
/*************************************
* Get the Error Message for @@Error
*************************************/
IF @@TRANCOUNT > 0 ROLLBACK
SELECT @ErrorCode = ERROR_NUMBER()
, @Return_Message = @ErrorStep + ' '
+ cast(ERROR_NUMBER() as varchar(20)) + ' line: '
+ cast(ERROR_LINE() as varchar(20)) + ' '
+ ERROR_MESSAGE() + ' > '
+ ERROR_PROCEDURE()
/*************************************
* Return from the Stored Procedure
*************************************/
RETURN @ErrorCode -- =0 if success, <>0 if failure
END CATCH
答案 1 :(得分:3)
首先,数据库相当可靠。如果他们失败了,那么你处理个人交易会遇到更大的问题。所以我的反馈是你有太多的错误检查一个简单的交易。失败的插入是一种不寻常的事件,通常你不会编写代码来处理它。
其次,此代码实际上不会“捕获”错误:
IF @ErrorCode <> 0
SQL语句中的错误将中止存储过程并返回到客户端。您必须try ... catch才能在存储过程中实际处理错误。
第三,我尽量避免raiserr
。它可以在服务器和客户端都做出意想不到的事情。相反,请考虑使用output
参数将错误信息返回给客户端程序。