我正在尝试调试一个用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(这是第一次给我),但我无法弄清楚要追踪的内容:虽然我可以获取跟踪输出发送到数据库的查询,但它们是opaque在某种意义上说我无法向下钻取到被调用的Expression-UDF:我可以跟踪调用的实际存储过程,但是没有列出此过程调用的UDF.我错过了什么吗?我猜不会...
编辑#2:尽管(自动)接受的答案确实跟踪了函数调用 - 非常有用,谢谢 - 它无助于找出传递给函数的参数.当然,这对于调试递归函数至关重要.如果我发现任何溶剂,我会发布...
为什么不使用SQL Profiler添加语句级事件?
编辑:为存储过程添加事件:SP:Stmt Starting或SP:Stmt Completed使用变量进行调试,如果需要,即设置@ debug ='我在这里'; UDF虽然不是技术上存储的过程,但会跟踪语句级事件.
在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
那对你来说够了吗?