我有一个SP(存储过程),它包含一些T-SQL语句.....
所有T-sql语句都在事务块中,并且通过发生任何错误,我回滚所有事情。
像这样:BEGIN TRANSACTION
.....
.....
IF @X=1
BEGIN
declare cu cursor for select col1,col2 from Table1 where Id=@Y
open cu
fetch next from cuinto @A, @B
while @@Fetch_Status = 0
BEGIN
.....
......
IF @@ERROR <>0
BEGIN
ROLLBACK TRANSACTION
RETURN
END
END
.....
.....
Sp没有正常运行,我找不到它的研究...... 我认为通过将一些数据插入表中来记录sp中的每个操作是个好主意 我的问题是:
因为它使用了一个事务,所以每次插入都会被回滚.....
你有什么看法?还有其他办法吗?
谢谢
答案 0 :(得分:5)
3件事:
1)如果您不需要,请不要使用游标。
2)您可以使用RAISERROR WITH LOG或inserting data into a table variable进行日志记录,然后在回滚事务后将其插入到真实表中。这是可能的,因为表变量是与事务无关的
3)使用try catch块
答案 1 :(得分:3)
没有理由现在使用@@ ERROR:TRY / CATCH更可靠。要了解更多,我建议阅读Erland Sommarskog的"Error Handling in SQL 2005 and Later",这是关于该主题的权威文章之一
在这种情况下,没有TRY / CATCH,一些错误是批量中止:这意味着代码停止并且没有错误被捕获。使用TRY / CATCH修复此问题,但编译错误除外。
此模板取自我之前的回答Nested stored procedures containing TRY CATCH ROLLBACK pattern?
CREATE PROCEDURE [Name]
AS
SET XACT_ABORT, NOCOUNT ON
DECLARE @starttrancount int
BEGIN TRY
SELECT @starttrancount = @@TRANCOUNT
IF @starttrancount = 0
BEGIN TRANSACTION
[...Perform work, call nested procedures...]
IF @starttrancount = 0
COMMIT TRANSACTION
END TRY
BEGIN CATCH
IF XACT_STATE() <> 0 AND @starttrancount = 0
ROLLBACK TRANSACTION
RAISERROR [rethrow caught error using @ErrorNumber, @ErrorMessage, etc]
-- if desired INSERT ExceptionLogTable () ..
END CATCH
GO
如果使用SET XACT_ABORT ON(我认为应该是最佳实践),那么在任何CATCH块中@@ trancount为零。因此,除了抛出错误之外,您还可以在此处写入日志记录表。
答案 2 :(得分:1)
我重写了您的代码,使用Transaction
和Try Catch
CREATE PROCEDURE [dbo].[mySP]
(
@X int, @Y int,
@Return_Message VARCHAR(1024) = '' OUT
)
AS
SET NOCOUNT ON;
Declare @A varchar(100) @B varchar(100)
BEGIN TRY
BEGIN TRAN
IF @X=1
BEGIN
declare cu cursor for select col1,col2 from Table1 where Id=@Y
open cu
fetch next from cu into @A, @B
while @@Fetch_Status = 0
BEGIN
-- .....
-- do your stuff
FETCH NEXT FROM cu into @A, @B
END
END
COMMIT TRAN
SELECT @Return_Message = 'All OK'
/*************************************
* Return from the Stored Procedure
*************************************/
RETURN 1 -- success
END TRY
BEGIN CATCH
/*************************************
* if errors rollback
*************************************/
IF @@TRANCOUNT > 0 ROLLBACK
SELECT @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 0 -- fail
END CATCH
SP使用:
declare @ret int, @Return_Message VARCHAR(1024)
EXEC @ret = mySP 1, 2, @Return_Message OUTPUT
-- the SP Fail so print or store the return message with errors ...
if @ret = 0 print @Return_Message
答案 3 :(得分:-2)
您也可以使用Exception Handling来实施Try Catch
Begin Try
BEGIN TRANSACTION
.....
.....
IF @X=1
BEGIN
declare cu cursor for select col1,col2 from Table1 where Id=@Y
open cu
fetch next from cuinto @A, @B
while @@Fetch_Status = 0
BEGIN
.....
......
//Your insert statement....
END
.....
.....
Commit Tran
End Try
Begin Catch
Rollback Tran
DECLARE @ErrorMessage NVARCHAR(4000);
DECLARE @ErrorSeverity INT;
DECLARE @ErrorState INT;
SELECT @ErrorMessage = ERROR_MESSAGE(),
@ErrorSeverity = ERROR_SEVERITY(),
@ErrorState = ERROR_STATE();
-- Use RAISERROR inside the CATCH block to return
-- error information about the original error that
-- caused execution to jump to the CATCH block.
RAISERROR (@ErrorMessage, -- Message text.
@ErrorSeverity, -- Severity.
@ErrorState -- State.
);
End Catch