使sp_tracegenerateevent在存储过程中工作

时间:2018-04-19 14:11:01

标签: sql-server debugging

我正在调试从BizTalk调用的存储过程。

在之前的帖子中,有人建议使用sp_trace_generateevent。 [Use SQL Debugger when stored proc called by an external process

因为我需要显示一个变量,所以我想出了以下内容,它可以工作,我可以看到SQL Profiler中的值(使用EventClass = UserConfigurable:0“

Declare @message nvarchar(128)
Set @message = 'Hello World 2 ' 
exec sp_trace_generateevent @event_class=82, @userinfo = @message 

enter image description here

但是当我把它放在问题存储过程中的“BEGIN CATCH”中时,我在profiler中看不到任何内容:

BEGIN CATCH 
   DECLARE @message nvarchar(128)
   SET @message = LTRIM(STR(ERROR_MESSAGE())) 
   exec sp_trace_generateevent @event_class=82, @userinfo = @message 
   SET @CatchErrors = 
            'Catch: [LTL].[CreateShipment]  - ErrorNumber: '+LTRIM(STR(ERROR_NUMBER()))
            + ' ErrorSeverity: '+LTRIM(STR(ERROR_SEVERITY()))
            + ' ErrorState: '+LTRIM(STR(ERROR_STATE()))
            + ' ErrorProcedure: '+LTRIM(STR(ERROR_PROCEDURE()))
            + ' ErrorLine: '+LTRIM(STR(ERROR_LINE()))
            + ' ErrorMessage: '+LTRIM(STR(ERROR_MESSAGE()))

END CATCH

然后我在Catch中放了一个Catch:

BEGIN CATCH 
   BEGIN TRY 
      DECLARE @message nvarchar(128)
      SET @message = LTRIM(STR(ERROR_MESSAGE())) 
      exec sp_trace_generateevent @event_class=82, @userinfo = @message 
   END TRY 
   BEGIN CATCH 
      SET @Message = 'Error in sp_trace_generateevent' 
   END CATCH 
   SET @CatchErrors = 
            'Catch: [LTL].[CreateShipment]  - ErrorNumber: '+LTRIM(STR(ERROR_NUMBER()))
            + ' ErrorSeverity: '+LTRIM(STR(ERROR_SEVERITY()))
            + ' ErrorState: '+LTRIM(STR(ERROR_STATE()))
            + ' ErrorProcedure: '+LTRIM(STR(ERROR_PROCEDURE()))
            + ' ErrorLine: '+LTRIM(STR(ERROR_LINE()))
            + ' ErrorMessage: '+LTRIM(STR(ERROR_MESSAGE()))


END CATCH

现在我可以在分析器中看到“sp_trace_generateevent中的SET @Message ='错误”,但我真的需要查看错误的原因。

我在SSMS中测试时遇到的问题无法再现,只有当我从BizTalk调用时。我的意图是将@CatchErrors(作为输出参数)冒泡回BizTalk,但它也不起作用。

此外 - BizTalk正在与拥有SQL SysAdmin的用户一起运行(它在我的开发机器上)。

使用master..sp_tracegeneratedevent

时也会得到相同的结果

基于@Jeroen的回复,我切换到了这个,但仍然遇到了一些错误。

   DECLARE @message nvarchar(128)
   BEGIN TRY 
      SET @message = Convert(nvarchar(128),SUBSTRING(ERROR_MESSAGE(),1,128))
      exec sp_trace_generateevent @event_class=82, @userinfo=@message 
   END TRY 

更新#1:这让我感到沮丧。当我在SQL中测试时它可以工作,但是当我从BizTalk测试它没有。所以我真的想要一个调试功能。我现在抓住我捕获的捕获物......而且它们都在捕捉,我不知道为什么。相同的代码在除以零的简单示例中工作正常。更复杂的是,这是一个由BizTalk调用的存储过程调用的存储过程。如果我发现错误,我应该能够在我的主要和子存储过程中的@CatchErrors输出参数中将它返回给BizTalk。

BEGIN CATCH 
   DECLARE @message nvarchar(128)
   BEGIN TRY 
      SET @message = Convert(nvarchar(128),SUBSTRING(ERROR_MESSAGE(),1,128))
      exec sp_trace_generateevent @event_class=82, @userinfo=@message 
   END TRY 
   BEGIN CATCH 
      SET @Message = 'Error in sp_trace_generateevent' 
   END CATCH 

   BEGIN TRY 
       SET @CatchErrors = 
            'Catch: [RG].[CreateShipment]  - ErrorNumber: '+CAST(ERROR_NUMBER() AS VARCHAR(35)) 
            + ' ErrorSeverity: '+CAST(ERROR_SEVERITY() AS VARCHAR(35))
            + ' ErrorState: '+CAST(ERROR_STATE() AS VARCHAR(35)) 
            + ' ErrorProcedure: '+CAST(IsNull(ERROR_PROCEDURE(),'') AS VARCHAR(200)) 
            + ' ErrorLine: '+CAST(ERROR_LINE() AS VARCHAR(35)) 
            + ' ErrorMessage: '+CAST(ERROR_MESSAGE() AS VARCHAR(4000)) 
   END TRY 
   BEGIN CATCH 
      BEGIN TRY 
          SET @Message = 'Error in Set @CatchErrors=' 
          SET @CatchErrors = 
                'Catch: [LTL.CreateShipmentStopLineItem]- Error: ' + CAST(ERROR_MESSAGE() AS VARCHAR(4000)) 
      END TRY 
      BEGIN CATCH 
         SET @Message = 'Error in Set @CatchErrors2' 
      END CATCH 
   END CATCH 
END CATCH

当前的Profiler结果: enter image description here

更新#2 - 在SSMS中进行测试:

我正在使用SSMS进行测试,没有一个问题存在问题。如果我不止一次运行它,它会在Print语句中出现违反主键的情况。

 Declare @shipstopline LTL.TT_ShipmentStopLineItem
 DECLARE @messageID bigint
 DECLARE @CatchErrorsResult varchar(max) 
 insert into @shipstopline values ('2', '1', 'Eggs','1','2','3','1','100','1','12','1','1','1','10','20','1')

 EXEC LTL.CreateShipmentStopLineItem @MessageId = 2, @ShipmentStopID=1, @CreateBy=108004, @ShipmentStopLineItem=@shipstopline, @loopid=1, @catchErrors=@CatchErrorsResult OUT 
 select RowCreated, * from LTL.ShipmentStopLineItem order by LTL.ShipmentStopLineItem.RowCreated desc
 print @CatchErrorsResult

2 个答案:

答案 0 :(得分:1)

好吧,如果你试试这个:

SET XACT_ABORT ON;
BEGIN TRY   
    SELECT 1 / 0;
END TRY
BEGIN CATCH
    DECLARE @message nvarchar(128);
    SET @message = LTRIM(STR(ERROR_MESSAGE()));
    exec sp_trace_generateevent @event_class=82, @userinfo = @message
END CATCH

您可以立即获得有关错误的反馈:

  

Msg 8114,Level 16,State 5,Line 8转换数据类型时出错   nvarchar浮动。

那是因为你STR()打电话给你的是不正确的事情 - STR格式化浮点值,只有那些。 (为了灵活转换,请使用FORMAT和/或CONCAT,后者总是隐式地将内容转换为字符串而不会抱怨。)

除此之外,存储过程的第一个参数是@eventid,而不是@event_class(这通常是一个错误,但扩展存储过程更灵活 - 你可以调用参数@banana它仍然有效。但是,为了清楚起见,我们应该使用记录的名称。所以:

SET XACT_ABORT ON;
BEGIN TRY   
    SELECT 1 / 0;
END TRY
BEGIN CATCH
    DECLARE @message nvarchar(128) = ERROR_MESSAGE();
    EXEC sp_trace_generateevent @eventid=82, @userinfo = @message;
END CATCH

在我的探查器中,这会产生一个带有

UserConfigurable:0事件
  

遇到零错误。

请注意,如果没有TRY / CATCH,即使没有通过Exception事件生成自己的跟踪事件,您仍然可以获得错误。

答案 1 :(得分:0)

事实证明,BizTalk调用Stored Proc两次,一次使用FmtOnly = On,再一次使用FmtOnly = Off。我在第一次调用后得到了无效的强制转换异常,因此Stored Proc基本上没有真正执行。由于FmtOnly = On,我被分析器误导了,认为它实际上正在执行我在那里看到的语句。因此sp_TraceGenerateEvent实际上并不在FmtOnly = On的第一次传递上运行,但是当我超过其他错误时,它在第二次传递中运行正常,FmtOnly = Off。

参考:类似的questoin我发布了为什么SQL Profiler在SSMS运行和同一存储过程的BizTalk运行之间看起来不同的原因:Can SQL Begin Try/Catch be lying to me (in the profiler)?