2008-12-09 80 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團隊的成員。