如何编写一个t-sql程序来捕获最终的事务引发错误

时间:2015-08-11 16:52:13

标签: sql-server tsql

我是T-SQL编程的新手。我需要编写一个主程序来执行多个事务。我如何构建程序,以便每个事务不会中止。相反,该过程将引发错误并在所有事务完成运行后将它们报告回输出参数中的主程序。如果可以,请提供伪代码。感谢。

3 个答案:

答案 0 :(得分:0)

你可以使用try / catch

BOL - TRY/CATCH

Here's an example

我之前已将逻辑封装到存储过程中,并在TRY / CATCH块中放入exec语句。在CATCH中,您可以使用此链接获取错误信息(链接中的示例B)

BOL - ERROR_MESSAGE

类似于 -

BEGIN TRY
    BEGIN TRAN
    EXEC StoredProcedure01
    EXEC StoredProcedure02
    COMMIT
END TRY
BEGIN CATCH
    ROLLBACK TRAN
    SELECT
        ERROR_NUMBER() AS ErrorNumber
        ,ERROR_SEVERITY() AS ErrorSeverity
        ,ERROR_STATE() AS ErrorState
        ,ERROR_PROCEDURE() AS ErrorProcedure
        ,ERROR_LINE() AS ErrorLine
        ,ERROR_MESSAGE() AS ErrorMessage;
END CATCH;
GO

答案 1 :(得分:0)

您需要关注Exception handling and nested transactions

中的模板
create procedure [usp_my_procedure_name]
as
begin
    set nocount on;
    declare @trancount int;
    set @trancount = @@trancount;
    begin try
        if @trancount = 0
            begin transaction
        else
            save transaction usp_my_procedure_name;

        -- Do the actual work here

lbexit:
        if @trancount = 0   
            commit;
    end try
    begin catch
        declare @error int, @message varchar(4000), @xstate int;
        select @error = ERROR_NUMBER(), @message = ERROR_MESSAGE(), @xstate = XACT_STATE();
        if @xstate = -1
            rollback;
        if @xstate = 1 and @trancount = 0
            rollback
        if @xstate = 1 and @trancount > 0
            rollback transaction usp_my_procedure_name;

        raiserror ('usp_my_procedure_name: %d: %s', 16, 1, @error, @message) ;
    end catch   
end
go

正如您所看到的,您无法始终继续,因为有时异常已经在您捕获事务时中止了事务(典型示例是死锁异常1205)。并且必须使用保存点并在异常情况下恢复到保存点,以保持数据库的一致性。但是,如果可能,您不会中止调用者的工作。

答案 2 :(得分:0)

我可能会考虑尝试这个。每个事务都是一个单独的存储过程,其中有一个整体存储过程,它依次调用每个事务。将所需的错误信息保存在表变量中。在每个proc的catch块中,回滚该事务,然后将带有错误信息的表变量的数据插入到日志表中。不要将失败返回到调用proc。

如果要实时报告主过程中的错误,可以从最后的日志表中进行选择。

如果您在调用proc的开头创建一个batchid并且它是您调用的每个proc的输入变量,并且在您添加到日志记录表的信息中包含该数据,那么它将最有效。然后,如果在非工作时间内procs多次失败,则所有这些都有错误,并且可以看到与之关联的批处理。这有助于追踪问题。

在设计日志记录表时,您需要考虑一下每个过程需要哪些信息。我建议您存储的部分内容是发送到proc的任何输入变量。此外,如果您使用动态SQl,那么也存储生成的sql。如果您可以识别运行proc的用户,那么这对于跟踪权限问题也很有用。

拥有日志记录表比在运行时返回错误更有用。您可以查找趋势,查看是否经常发生相同的错误,查看导致失败的信息以及如果您选择同时记录变量以获得成功运行的成功信息。

这些都不是易于编写代码的开箱即用。您需要进行大量设计,以确定在解决流程问题时,哪些信息对于长期有用。您需要获得的详细信息是基于数据使用方式和您希望了解的故障的业务决策。因此,我们无法为您做出这一决定。