我们正在经历从DB2切换到SQL Server 2008R2的过程,我对TSQL有点不熟悉。任何有助于更好地了解正在发生的事情的帮助都会很好。我们创建了一个名为RethrowError的过程:
CREATE PROCEDURE RethrowError
AS
BEGIN
-- Return if there is no error information to retrieve.
IF ERROR_NUMBER() IS NULL
RETURN;
PRINT 'yo error';
DECLARE
@ErrorMessage NVARCHAR(4000),
@ErrorNumber INT,
@ErrorSeverity INT,
@ErrorState INT,
@ErrorLine INT,
@ErrorProcedure NVARCHAR(200);
-- Assign variables to error-handling functions that
-- capture information for RAISERROR.
SELECT
@ErrorNumber = ERROR_NUMBER(),
@ErrorSeverity = ERROR_SEVERITY(),
@ErrorState = ERROR_STATE(),
@ErrorLine = ERROR_LINE(),
@ErrorProcedure = ISNULL(ERROR_PROCEDURE(), '-');
-- Build the message string that will contain original
-- error information.
SELECT @ErrorMessage = N'Error %d, Level %d, State %d, Procedure %s, Line %d, ' +
'Message: '+ ERROR_MESSAGE();
PRINT 'yo doin something';
-- Raise an error: msg_str parameter of RAISERROR will contain
-- the original error information.
RAISERROR
(
@ErrorMessage,
@ErrorSeverity,
1,
@ErrorNumber, -- parameter: original error number.
@ErrorSeverity, -- parameter: original error severity.
@ErrorState, -- parameter: original error state.
@ErrorProcedure, -- parameter: original error procedure name.
@ErrorLine -- parameter: original error line number.
);
PRINT 'yo end';
RETURN;
END
GO
我们创建该过程的原因纯粹是为了在将来扩展错误而无需触及所有过程。 我为调试目的添加了一些PRINT行。
我的主要问题是我们有程序A,如果失败,它会执行RethrowError,我会看到消息
yo error
yo doin something
yo end
正如所料。
CREATE PROCEDURE dbo.A
AS
BEGIN
SET NOCOUNT ON;
DECLARE & SET VARIABLES;
BEGIN TRY
BEGIN TRANSACTION MaintainTarget
DO SOME STUFF
END TRY
BEGIN CATCH
EXEC RethrowError;
IF (XACT_STATE()) = -1
BEGIN
PRINT
N'The transaction is in an uncommittable state. ' +
'Rolling back transaction.'
ROLLBACK TRANSACTION;
END;
IF (XACT_STATE()) = 1
BEGIN
PRINT
N'The transaction is committable. ' +
'Rolling back transaction.'
ROLLBACK TRANSACTION;
END;
RETURN -101;
END CATCH;
RETURN;
END
GO
但是,我们创建了一个执行许多过程的过程,当嵌套过程(即过程B调用过程A)失败时,我看到的唯一消息是
yo error
yo doin something
我不太明白为什么最后一条消息不再显示。
程序B类似于程序A,但在捕获方面略有不同。
CREATE PROCEDURE dbo.B
AS
BEGIN
SET NOCOUNT ON;
DECLARE & SET VARIABLES;
BEGIN TRY
DO SOME STUFF
END TRY
BEGIN CATCH
COMMIT;
RETURN -101;
END CATCH;
RETURN;
END
任何有助于更好地了解正在发生的事情的帮助都将受到赞赏。
答案 0 :(得分:3)
我允许自己编辑你的代码以模仿bahaviour,但保持简单(你的工作,实际上;)。
你的procA工作正常,因为在procA的CATCH块内调用了RethrowError过程,一切都在执行。但在你的第二种情况下,它仍然发生在procB的TRY块内!因此,在调用RethrowError中的RAISERROR后,procB的CATCH部分立即激活。
这个简单的例子演示了TRY-CATCH的这种行为:
begin try
select 1/0
print 'doesnt show - div error'
end try
begin catch
print 'oops'
select 1/0
print 'this one shows because its in CATCH!'
end catch
这是您的简化代码:
-- "proc B" start
begin try
-- "proc A" start (works fine alone)
begin try
begin tran
select 1/0 --error
end try
begin catch
print 'yo error';
RAISERROR ('RE from RethrowError', 16, 1) --comment this out and see what happens
print 'yo end';
IF (XACT_STATE())=-1 or (XACT_STATE())=1
BEGIN
PRINT N'Rolling back transaction.'
ROLLBACK TRANSACTION;
end
end catch -- "proc A" ends
end try
begin catch
select error_message(), error_severity(), error_state() --
print 'outer catch';
commit;
end catch;
希望这有帮助。