如何跟踪T-SQL函数调用

时间:2008-12-09 12:45:16

标签: tsql debugging trace user-defined-functions

我正在尝试调试一个用T-SQL UDF编写的相当复杂的公式求值程序(不要问)递归(但间接通过中间函数)调用自己,blah,blah。

当然,我们有一个错误。

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

对UDF执行相同操作会产生编译时消息:

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

我收到消息(PRINT做了一些像重置@@ROWCOUNT这样的东西,在UDF中肯定是禁止的,但是我如何追踪调用?我想要打印出这条迹线,所以我可以通过调试器中的调用来研究它而不会分心...

编辑:我曾尝试使用SQL Profiler(这对我来说是第一次),但我无法弄清楚要追踪的内容:虽然我可以获得跟踪输出发送到数据库的查询,它们是不透明的,因为我无法向下钻取到被调用的Expression-UDF:我可以跟踪调用的实际存储过程,但是没有列出此过程调用的UDF。我错过了什么吗?我猜不是......

编辑#2:虽然(自动)接受的答案会跟踪函数调用 - 非常有帮助,谢谢 - 它无助于找出传递的参数到功能。当然,这在调试递归函数中至关重要。如果我发现任何溶剂,我会发布...

9 个答案:

答案 0 :(得分:28)

为什么不使用SQL Profiler添加语句级事件?

编辑:为存储过程添加事件:SP:Stmt Starting或SP:Stmt Completed 如果需要,使用变量进行调试,即设置@ debug ='我在这里'; UDF虽然不是技术上存储的过程,但会跟踪语句级事件。

答案 1 :(得分:12)

在SQL事件探查器中,您需要:SP:Starting,SP:StmtStarting,SP:Completed,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

对你来说够了吗?

答案 2 :(得分:4)

This看起来像你需要的,但它只适用于Visual Studio的团队/专业版。

答案 3 :(得分:1)

使用SQL事件探查器,我建议您在第一次添加事件时过度使用,以便让您了解所需内容。如果没有测试,我会为SP添加事件:StmtStarted(或已完成或两者),SQL:StmtStarted(再次完成或两者)。

答案 4 :(得分:0)

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

有时您无权运行SQL事件探查器,因为它会降低服务器速度 - 请让您的DBA授予您Dev开发服务器的权限。他们应该没有任何问题。

答案 5 :(得分:0)

在过去,我不得不采用UDF中的典型值,然后在单独的查询窗口中仅运行udf部分作为直接SQL而不是udf,使用典型值作为使用声明和a设置的变量设定声明。如果它是从一个表运行而不是只有一个值,我会设置一个带有输入值的临时表或表变量,然后通过UDF中的sql运行它们(但是再次作为直接SQL而不是UDF)通过光标。通过运行直接SQL,您可以在其中包含打印语句以查看发生的情况。我知道这是一种痛苦,但它确实有效。 (我在创建/调试触发器时会经历一个简单的过程,使用我的测试值设置#inserted和#deleted,然后测试我打算放入触发器的代码,然后全局替换#with no,并添加create trigger代码。 )

答案 6 :(得分:0)

也许您可以使用SQL CLR来执行此处所述的跟踪 How to log in T-SQL

答案 7 :(得分:0)

您是否可以使用您的函数,并对其进行第二次复制,但返回一个包含附加列的表类型以供调试信息。

例如,下面的mySum函数

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)

会变成

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)

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

答案 8 :(得分:0)

我使用SQL SPY来完成你正在寻找的东西。

SQL SPY

SQL SPY Feature Documentation

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

此功能是为MS SQL Server 2005 \ 2008设计的,但可以在有限范围内与MS SQL Server 2000一起使用。它能够记录和报告传入SQL。如何使用这些功能:见

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