2008-12-09 13 views
20

Ich versuche, ein ziemlich kompliziertes Formel-Evaluator in T-SQL-UDFs geschrieben (nicht fragen), dass rekursiv (aber indirekt über eine Zwischenfunktion) sich selbst nennt, blah , Blah.Wie T-SQL-Funktionsaufrufe zu verfolgen

Und natürlich haben wir einen Fehler.

Mit PRINT-Anweisungen (die dann von ADO.NET gelesen werden können, indem ein Handler für das InfoMessage-Ereignis implementiert wird) kann ich eine Ablaufverfolgung für gespeicherte Prozeduren simulieren.

das gleiche für UDF Ergebnisse in einer Kompilierung Nachricht Doing:

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

bekomme ich die Meldung (PRINT hat einige Sachen wie @@ROWCOUNT Zurücksetzen die definitly ist ein no-no in SEF, aber wie kann ich Spur durch die Aufrufe? Ich möchte diese Trace ausgedruckt haben, so dass ich es studieren kann, ohne abgelenkt zu werden durch die Aufrufe im Debugger ...

EDIT: Ich habe versucht, den SQL Profiler (this war ein erstes Mal für mich), aber ich kann nicht herausfinden, wofür ich nachzeichnen soll: Alt Obwohl ich den Trace dazu bringen kann, die an die Datenbank gesendeten Abfragen auszugeben, sind sie in dem Sinne undurchsichtig, dass ich nicht zu den aufgerufenen Expression-UDFs gehen kann: Ich kann die aufgerufenen Stored Procedures verfolgen, aber die so aufgerufenen UDFs Verfahren sind nicht aufgeführt. Fehle ich etwas? Ich denke nicht ...

EDIT # 2: Allthough die (Auto-) akzeptierte Antwort tut verfolgen die Funktion aufruft - sehr hilfreich, Dank - es ist nicht herauszufinden, hilft, welche Parameter waren auf den übergebenen Funktion. Dies ist natürlich in Debugging rekursive Funktionen erforderlich. Ich werde posten, wenn ich irgendeine Lösung überhaupt finde ...

+0

Ja, schauen Sie sich die Antwort von Matthieu unten an, in der erläutert wird, welche Ereignisse Sie in Ihrem Profiler-Setup hinzufügen müssen. In der Standardeinstellung werden nur einige Ereignisse erfasst, die für die Fehlerbehebung nicht erforderlich sind. –

Antwort

26

Warum nicht SQL Profiler mit Statement-Level-Events hinzugefügt?

bearbeiten: In Veranstaltungen für Stored Procedures: SP: Stmt starten oder SP: Stmt Verwenden Variablen abgeschlossen, wenn nötig zu debuggen, das heißt set @ debug = 'Ich bin hier'; UDFs, obwohl keine technisch gespeicherten Prozeduren, werden mit den Ereignissen auf Anweisungsebene verfolgt.

+0

Sicher, aber es ist nicht Stored Procedures interessiert mich, aber UDFs. Diese sind in T-SQL ein völlig anderes Biest und haben wirklich harte Restriktionen ... –

+3

SP: StmtStarting behandelt auch Funktionen. Für ein Beispiel siehe meine Antwort weiter unten. –

0

Ich zweite der SQL Profiler Vorschlag. Nehmen Sie sich etwas Zeit, um es so einzurichten, dass nur die Ereignisse, an denen Sie interessiert sind, protokolliert werden, um die Ausgabegröße zu verringern. Sie können die Ablaufverfolgung in eine Datei ausgeben - ich habe diese Datei dann häufig wieder in eine Tabelle geladen, um die Analyse zu ermöglichen. (extrem praktisch für die Performance-Analyse, obwohl zweifellos jemand mir sagen wird, dass 2008 das alles in Somwere gebaut hat)

Manchmal haben Sie keine Berechtigungen zum Ausführen von SQL Profiler, da es den Server verlangsamt - fragen Sie Ihr DBA gewährt Ihnen die Erlaubnis auf Ihrem Dev-Server. Sie sollten damit keine Probleme haben.

+0

Ich habe das versucht, es funktioniert nicht wirklich: Obwohl die Ablaufverfolgung die ursprüngliche gespeicherte Prozedur zeigt, die aufgerufen wurde, sind die tatsächlichen UDFs (Ausdrücke) nicht aufgeführt, und so schaue ich immer noch nur auf eine Blackbox. –

+0

Hmm, ich habe keinen SQL Profiler vor mir (aktueller Auftritt ist Oracle-basiert).Vielleicht kann jemand, der die richtigen Ereignisse gefunden hat, die UDF-Informationen erhalten (oder sagen, dass das nicht möglich ist). – kpollock

+0

Stored Procedure: SP: StmtStarting oder SP: StmtCompleted Sie können auch lokale Variablen hinzufügen und Set @ debug = 'ich bin hier', die in Profiler – SqlACID

1

Verwenden Sie SQL Profiler, ich empfehle Ihnen, beim ersten Hinzufügen von Ereignissen über Bord zu gehen, damit Sie ein Gefühl dafür bekommen, was Sie brauchen. Ohne Tests würde ich die Ereignisse für SP hinzufügen: StmtStarted (oder Completed oder beides), SQL: StmtStarted (wieder Completed oder Both).

0

Nun, in der Vergangenheit musste ich typische Werte nehmen, die in der UDF sein würden und dann nur den udf-Teil in einem separaten Abfragefenster als straight SQL und nicht als udf mit den typischen Werten als Variablen ausführen, die mit declare und eine gesetzte Aussage.Wenn es von einer Tabelle aus ausgeführt wird, anstatt nur einen Wert zu haben, würde ich eine temporäre Tabelle oder Tabellenvariable mit den Eingabewerten einrichten und sie dann durch die SQL-Anweisung in der UDF (aber wiederum als SQL ohne UDF) durch a ausführen Mauszeiger. Durch Ausführen von straight SQL könnten Sie print-Anweisungen haben, um zu sehen, was passiert. Ich weiß, dass das ein Schmerz ist, aber es funktioniert. (Ich gehe durch einen ähnlichen Prozess beim Erstellen/Debuggen von Triggern, setup # inserted und #deleted mit meinen Testwerten und teste dann den Code, den ich in den Trigger legen möchte, dann global ersetze # durch nichts und füge den create trigger code hinzu.)

0

Vielleicht können Sie SQL CLR verwenden, um die Verfolgung zu tun, wie hier beschrieben How to log in T-SQL

4

This sieht aus wie, was Sie brauchen, aber es ist nur im Team/pro-Versionen von Visual Studio zur Verfügung.

0

Können Sie Ihre Funktion übernehmen und eine zweite Kopie davon erstellen, aber einen Tabellentyp mit einer zusätzlichen Spalte für Ihre Debuginformationen zurückgeben.

Zum Beispiel kann die mySum Funktion unter

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) 

wiederum würde in

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) 

keine ideale Lösung, aber nützlich nur einen Text zurückzukehren, um einen Fehler aufzuspüren.

12

Im SQL-Profiler benötigen Sie: SP: Starting, SP: StmtStarting, SP: Completed, SQL: BatchStarting. Dann erhalten Sie jeden Eintrag, verlassen Sie die Funktionen/gespeicherte Prozeduren.

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 

mit diesem, die ich erhalten:

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 

, dass genug für Sie ist?

0

Ich benutze SQL SPY, die das tut, was Sie suchen und mehr.

SQL SPY

SQL SPY Feature Documentation

SQL SPY Incoming SQL Sniffer zeigt den eingehenden SQL-Code der einzelnen Verbindungen (Enthält DDL und DML-Anweisung Tracking)

Diese Funktion ist für MS SQL Server 2005 \ 2008 ist , wird aber in begrenztem Umfang mit MS SQL Server 2000 arbeiten. Es hat die Fähigkeit, eingehende SQL-Nachrichten aufzuzeichnen und zu melden. So verwenden Sie die Funktionen: Siehe

Disclosure: Ich bin Teil des SQL SPY-Teams.

+0

Website ist tot, vielleicht dies wurde: https: // sqlspy. codeplex.com/ - Ich glaube nicht, dass dies die Frage beantwortet. –

Verwandte Themen