如何在Sql Server(2008)中为存储过程添加跟踪/调试输出

15
什么方法最接近于能够像log4net一样向一组存储过程添加调试信息?其中一些过程将工作委托给其他过程,我希望从两个过程中获得跟踪信息。
在开发过程中,我已经在其中加入了打印和选择语句,并且理想情况下,我希望能够根据它是正常操作还是故障排除而以不同的模式运行proc并获得更多或更少的输出。
在这种特定情况下,主要存储过程将反复从代理作业运行,但在故障排除时可能会从管理工作室运行。
这些过程已经使用错误日志表和电子邮件设施来捕获引发的错误。我想追踪的是输入数据问题导致输出数据错误,但过程并未完全失败的情况,因此看到每个步骤所做的事情非常有用。
您知道哪些方法可以产生有意义且理想情况下可过滤的输出?
每个答案一个,以便我们可以看到最终排名;-)
欢迎使用开箱即用的答案,例如“不要 - 当您需要时,请使用管理工作室逐步进行”。

也许这个 Stack Overflow 链接可以帮到你:http://stackoverflow.com/questions/3829201/sql-select-print-out-results-of-stored-procedue/3832356#3832356 - adopilot
3个回答

14

大量的打印语句

例如

print 'Doing something...'
INSERT INTO foo(a) VALUES(1)
print @@ROWCOUNT

这个答案只是为了平衡一下,因为这里很安静。


1
我更喜欢在我的答案中使用[dbo].[PrintMessage]方法,以便轻松切换开关。 - Martin Smith
我同意,只是遵循流行观点,让受欢迎的答案保持在顶部。 - Tim Abell
@TimAbell 这些打印语句的输出是否在 SQL Server 中持久存在,以便进行故障排除? - Anto Varghese
据我所知,@Antoops没有这样做。 - Tim Abell

7

一个方法可能是检查 proc 是否从 SSMS 运行,并在此情况下触发一些自定义用户可配置的 SQL Server Profiler 事件。例如:

CREATE PROC foo
AS
DECLARE @debug bit = CASE WHEN APP_NAME() = 'Microsoft SQL Server Management Studio - Query' 
                          THEN 1 
                          ELSE 0 END

DECLARE @userinfo nvarchar(128)
DECLARE @userdata varbinary(8000)

--Do some work here

IF @debug = 1
BEGIN
--Do some custom logging 
    SET @userinfo = N'Some custom info'
    SET @userdata = CAST('Some custom data' AS varbinary(8000))
    EXEC sp_trace_generateevent @eventid = 82 /*Use 82-91*/
                               ,@userinfo = @userinfo 
                               ,@userdata = @userdata

END

实际上,我通常使用以下代码。根据需求可能会添加额外的代码将消息(和可能的步骤和状态值)记录到表中以满足“可过滤”的要求。

这样可以防止消息被打印出来,除非APP_NAME指示它在运行(英语版本的)SSMS中,并使用NOWAIT,因此消息会立即打印出来而不是等待缓冲区填充。

CREATE PROCEDURE [dbo].[PrintMessage] @message            NVARCHAR(MAX),
                                      @PrependCurrentTime BIT = 0
AS
    IF APP_NAME() LIKE 'Microsoft SQL Server Management Studio%' 
      BEGIN
          DECLARE @CurrentTimeString VARCHAR(30);

          SET @CurrentTimeString = ''

          IF @PrependCurrentTime = 1
            BEGIN
                SET @CurrentTimeString = CONVERT(VARCHAR(19), GETDATE(), 20) + ' '
            END

          RAISERROR('%s%s',0,1,@CurrentTimeString,@message) WITH NOWAIT

      END

1
注意:此操作需要特定的权限,可能在您的生产环境中无法使用!(我已经吃过亏了,哎!) - Tim Abell
1
整洁,也许值得将第二部分拆分成自己单独的答案。 - Tim Abell

1

不要添加跟踪输出,而是使用 SQL Server Management Studio 调试器按需逐步执行。

(添加此内容以查看人们是否更喜欢这种方法)


2
没错,这对于开发阶段来说是可以的,但在 PRD 中,有时需要为那些只执行并查看正在进行的操作以及可能失败的用户提供输出 ;) - Jorge Cornejo Bellido

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接