2008-12-09 85 views
20

我试图调试一个用T-SQL UDFs编写的相当复杂的公式评估器(不要问)递归(但间接通过中间函数)调用自己,等等,等等。如何跟踪T-SQL函数调用

而且,当然,我们有一个错误。

现在,使用PRINT语句(可以通过实现InfoMessage事件的处理程序从ADO.NET中读取),我可以模拟存储过程的跟踪。

做的UDF结果同样在编译时消息:

Invalid use of side-effecting or time-dependent operator in 'PRINT' within a function. 

我得到的消息(PRINT做一些东西,如重置@@ROWCOUNT这definitly是一个禁忌的UDF的,但我怎么能跟踪通过调用?我想打印出这个跟踪,所以我可以研究它,而不会因调试器中的调用而被分散注意力...

编辑:我试图使用SQL事件探查器对我来说是第一次),但我无法弄清楚要追查什么:Alt尽管我可以获取跟踪以输出发送到数据库的查询,但它们是不透明的,因为我无法深入到称为的Expression-UDF:我可以跟踪调用的实际存储过程,但是由此调用的UDF程序没有列出。我错过了什么吗?我想不是...

编辑#2: Allthough的(自动)接受的答案不跟踪函数调用 - 非常有帮助,感谢 - 它不会发现什么参数为传递的帮助功能。这当然是在调试递归函数中必不可少的。我会发布,如果我发现任何溶剂......

+0

是的,请查看下面Matthieu的答案,它解释了您需要添加到Profiler设置中的事件。默认情况下,它只捕获一些事件,而不是您需要进行故障排除的事件。 – 2009-02-18 18:27:53

回答

26

为什么不使用SQL事件探查器添加语句级事件?

编辑:添加事件存储过程:SP:语句启动或SP:语句完成 使用变量调试如果需要的话,即一套@调试=“我在这里”; UDF的虽然不是技术上存储的过程,但会跟踪语句级别的事件。

+0

当然,但它不是我感兴趣的存储过程,而是UDF。这些在T-SQL中是一个完全不同的野兽,并且具有非常严格的限制... – 2008-12-09 15:14:04

+3

SP:StmtStarting也处理函数。举一个例子,看看我的答案。 – 2009-02-17 16:02:16

0

我第二个SQL分析器的建议。花一些时间设置它,以便只记录您感兴趣的事件以减少输出大小。您可以将跟踪输出到文件 - 我经常将该文件加载回表中以启用分析。 (非常方便进行性能分析,但毫无疑问,有人会告诉我,2008年这一切都建立在somwehere ...)

有时候你不会有权限运行SQL Profiler,因为它会降低服务器的速度 - 问您的DBA授予您在开发服务器上的权限。他们不应该有任何问题。

+0

我已经试过了,它并没有真正的工作:虽然跟踪显示被调用的原始存储过程,但实际的UDF(表达式)没有列出,所以我仍然只是看着一个黑盒子。 – 2008-12-09 13:14:46

1

使用SQL事件探查器,我建议你在第一次添加事件时会过度,这会让你感觉到你需要什么。没有测试,我会添加SP的事件:StmtStarted(或完成或两者),SQL:StmtStarted(再次完成或两者)。

0

那么在过去,我不得不采取典型的值在UDF中,然后在单独的查询窗口中运行udf部分作为直接的SQL而不是udf使用典型的值作为变量设置声明和一套陈述。如果它是从一个表中运行而不是只有一个值,那么我会设置一个带有输入值的临时表或表变量,然后通过UDF中的sql运行它们(但又是直接的SQL而不是UDF)光标。通过运行正确的SQL,您可以在其中打印语句以查看正在发生的事情。我知道这是一个痛苦,但它的作品。 (我在创建/调试触发器时进行了一个simliar进程,使用我的测试值设置了#inserted和#deleted,然后测试了我打算放入触发器的代码,然后全局替换#并且添加了创建触发器代码。 )

4

This看起来像你所需要的,但它只是在Visual Studio团队/ Pro版本。

0

你可以把你的函数,并做它的第二个副本,但返回一个表类型与一个额外的列为您的调试信息。

例如,下面

CREATE FUNCTION mySum 
( 
    @param1 int, 
    @param2 int 
) 
RETURNS INT AS 
BEGIN 
    DECLARE @mySum int 

    SET @mySum = @param1 

    SET @mySum = @mySum + @param2 

    RETURN @mySum 

END 
GO 
SELECT dbo.mySum(1, 2) 

的mySum功能就会变成

CREATE FUNCTION mySumDebug 
( 
    @param1 int, 
    @param2 int 
) 
RETURNS @myTable TABLE 
(
    [mySum] int, 
    [debug] nvarchar(max) 
) 
AS 
BEGIN 
    DECLARE @debug nvarchar(max) 

    SET @debug = 'Declare @mySum variable. ' 
    DECLARE @mySum int 

    SET @debug = @debug + 'Set @mySum = @param1(' + CONVERT(nvarchar(50), @param1) + ') ' 
    SET @mySum = @param1 


    SET @debug = @debug + 'Add @param2(' + CONVERT(nvarchar(50), @param2) + ') to @mySum(' + CONVERT(nvarchar(50), @mySum) + ') ' 
    SET @mySum = @mySum + @param2 

    SET @debug = @debug + 'Return @mySum variable. ' 

    INSERT @myTable (mySum, debug) VALUES (@mySum, @debug) 

    RETURN 
END 
GO 
SELECT mySum, debug FROM dbo.mySumDebug(1, 2) 

不是一个理想的解决方案,但有用的只是返回一些文本,以帮助追踪一个错误。

12

在SQL事件探查器中,您需要:SP:开始,SP:StmtStarting,SP:已完成,SQL:BatchStarting。然后,你得到每一个条目,退出函数/存储过程。

alter FUNCTION [dbo].[ufn_mjf](@i numeric(10)) 
    RETURNS numeric(20) 
AS 
BEGIN 
declare @datapoint varchar(10) 

    set @datapoint = 'hello world' 

    return @i 
END 
go 
drop table foo 
go 
create table dbo.foo (foo_id numeric(10)) 
go 
delete from foo 
insert into foo (foo_id) values (1) 
insert into foo (foo_id) values (2) 

select foo_id, dbo.ufn_mjf(foo_id) from foo 

这一点,我得到:

SQL:BatchStarting alter FUNCTION [dbo].[ufn_mjf](@i numeric(10)) 
SQL:BatchStarting drop table foo 
SQL:BatchStarting create table dbo.foo (foo_id numeric(10)) 
SQL:BatchStarting delete from foo 
    insert into foo (foo_id) values (1) 
    insert into foo (foo_id) values (2) 
    select foo_id, dbo.ufn_mjf(foo_id) from foo 
SP:Starting select foo_id, dbo.ufn_mjf(foo_id) from foo 
SP:StmtStarting set @datapoint = 'hello world' 
SP:StmtStarting return @i 
SP:Completed select foo_id, dbo.ufn_mjf(foo_id) from foo 
SP:Starting select foo_id, dbo.ufn_mjf(foo_id) from foo 
SP:StmtStarting set @datapoint = 'hello world' 
SP:StmtStarting return @i 
SP:Completed select foo_id, dbo.ufn_mjf(foo_id) from foo 

是够长了吧?

0

我使用SQL SPY,它可以完成您正在寻找的任务以及更多功能。

SQL SPY

SQL SPY Feature Documentation

SQL SPY的传入SQL嗅探器显示每个连接的输入SQL代码(包括DDL和DML语句跟踪)

此功能是专为MS SQL服务器2005 \ 2008 ,但将在有限的范围内与MS SQL Server 2000协同工作。它具有记录和报告传入SQL的能力。如何使用这些功能:请参阅

披露:我是SQL SPY团队的成员。