2008-12-09 15 views
20

Próbuję debugować dość skomplikowany ewaluator formuły napisany w UDF T-SQL (nie pytaj), że rekursywnie (ale pośrednio poprzez funkcję pośrednią) nazywa się, bla , bla.Jak śledzić wywołania funkcji T-SQL

I, oczywiście, mamy błąd.

Teraz, używając instrukcji PRINT (które można następnie odczytać z ADO.NET poprzez implementację programu obsługi zdarzenia InfoMessage), mogę zasymulować śledzenie procedur składowanych.

robi to samo dla UDF skutkuje komunikatem czasu kompilacji:

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

dostaję komunikat (druk robi pewne rzeczy jak resetowanie @@ROWCOUNT który zdecydowanie jest nie-nie w UDF, ale jak mogę śladu ? pośrednictwem połączeń Chcę mieć ten ślad wydrukowany, więc mogę uczyć się go bez uzyskiwania rozproszony poprzez intensyfikację przez połączeń w debugera ...

EDIT: próbowałem użyć SQL Profiler (ta był dla mnie po raz pierwszy), ale nie potrafię wymyślić, na co mam uważać: Alt hough Mogę uzyskać śledzenie wyjściowe kwerendy wysyłane do bazy danych, są one nieprzezroczyste w tym sensie, że nie mogę drążyć do wyrażenia UDF o nazwie: Mogę wyśledzić rzeczywistą procedura składowana wywoływana, ale UDFs wywoływane przez to procedura nie są wymienione. Czy czegoś brakuje? Chyba nie ...

EDIT # 2: Allthough mierzy się (auto-) przyjął odpowiedź robi prześledzić funkcja nazywa - bardzo pomocne, dzięki - to nie pomaga w ustaleniu, jakie parametry były przeszedł do funkcjonować. Jest to oczywiście niezbędne w funkcjach rekursywnych debugowania. Będę publikować, jeśli znajdę jakiekolwiek rozwiązanie ...

+0

Tak, sprawdź odpowiedź Matthieu poniżej, która wyjaśnia, jakie wydarzenia musisz dodać w ustawieniach Profila. Domyślnie przechwytuje tylko kilka zdarzeń i nie są one potrzebne do rozwiązywania problemów. –

Odpowiedz

26

Dlaczego nie używać SQL Profiler z dodanymi zdarzeniami na poziomie instrukcji?

Edit: Dodawanie wydarzeń do procedur przechowywanych: SP: stmt uruchamiania lub SP: stmt Wykonane używać zmiennych do debugowania, jeśli to konieczne, to znaczy zestaw @ debug = 'Jestem tutaj'; UDF, choć nie są procedurami przechowywanymi technicznie, zostaną wykryte za pomocą zdarzeń na poziomie instrukcji.

+0

Oczywiście, ale nie są to zapisane procedury, którymi jestem zainteresowany, ale UDF. Są to zupełnie inne bestie w T-SQL i mają naprawdę surowe ograniczenia ... –

+3

SP: StmtStarting obsługuje również funkcje. Na przykład zobacz moją odpowiedź poniżej. –

0

I sekundę sugestii programu SQL Profiler. Poświęć trochę czasu na skonfigurowanie, aby rejestrowane były tylko zdarzenia, które Cię interesują, aby zmniejszyć rozmiar wyjściowy. Możesz wyprowadzić śledzenie do pliku - często włączyłem ten plik z powrotem do tabeli, aby umożliwić analizę. (bardzo przydatny do analizy wydajności, ale bez wątpienia ktoś powie mi, że 2008 ma to wszystko wbudowane gdzieś ...)

Czasami nie będziesz mieć uprawnień do uruchamiania programu SQL Profiler, ponieważ spowalnia to serwer - zapytaj DBA, aby udzielić ci pozwolenia na serwerze Dev. Nie powinni mieć z tym żadnych problemów.

+0

Próbowałem tego, to naprawdę nie działa: Chociaż ślad pokazuje oryginalną procedurę przechowywaną, która została wywołana, rzeczywiste UDF (wyrażenia) nie są wymienione, więc wciąż patrzę na czarne pole. –

+0

Hmm, nie mam przed sobą programu SQL Profiler (obecny gig jest oparty na Oracle).Może ktoś, kto może znaleźć odpowiednie zdarzenia, aby ustawić, aby uzyskać informacje UDF (lub powiedzieć, że nie jest to możliwe). – kpollock

+0

Procedura składowana: SP: StmtStarting lub SP: StmtCompleted Możesz także dodać zmienne lokalne i ustawić Set @ debug = "Jestem tutaj", który pojawi się w profilerze. – SqlACID

1

Skorzystaj z programu SQL Profiler, zalecam, abyś za pierwszym razem dodawał wydarzenia, dzięki czemu możesz poczuć, czego potrzebujesz. Bez testowania dodałbym zdarzenia dla SP: StmtStarted (lub Completed lub oba), SQL: StmtStarted (ponownie Completed lub Both).

0

W przeszłości musiałem przyjmować typowe wartości, które byłyby w UDF, a następnie uruchamiać tylko część udf w oddzielnym oknie zapytania jako prosty SQL, a nie udf, używając typowych wartości jako zmiennych ustawionych za pomocą deklaracji i zestaw instrukcji.Jeśli jest uruchamiany z tabeli, zamiast mieć tylko jedną wartość, ustawiłbym tabelę tymczasową lub zmienną tabeli z wartościami wejściowymi, a następnie uruchomiłbym je przez sql w UDF (ale znowu jako prosty SQL, a nie UDF) przez kursor. Po uruchomieniu prostej instrukcji SQL możesz mieć instrukcje drukowania, aby zobaczyć, co się dzieje. Wiem, że to jest ból, ale działa. (Przechodzę przez prostą procedurę podczas tworzenia/debugowania wyzwalaczy, ustawienia #inserted i #deleted z moimi wartościami testowymi, a następnie testuję kod, który zamierzam umieścić w wyzwalaczu, następnie globalne zastąpienie # nic i dodam kod wyzwalacza create.)

4

This wygląda co trzeba, ale jest ona dostępna tylko w wersji pro/zespołu Visual Studio.

0

Czy możesz wziąć swoją funkcję i zrobić jej drugą kopię, ale zwracając typ tabeli z dodatkową kolumną dla informacji debugowania.

Na przykład, funkcja mySum poniżej

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) 

zamieni się

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) 

nie jest idealne rozwiązanie, ale przydatny tylko do powrotu jakiś tekst, aby pomóc wyśledzić błąd.

12

W programie profilującym SQL potrzebne są: SP: Początek, SP: StmtStarting, SP: Zakończone, SQL: BatchStarting. Następnie dostajesz każdy wpis, wyjście z funkcji/zapisanych procedur.

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 

z tym, mam:

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 

jest to dla Ciebie za mało?

0

Używam SQL SPY, która robi to, czego szukasz i więcej.

SQL SPY

SQL SPY Feature Documentation

SQL Szpiega Przychodzące SQL Sniffer pokazuje przychodzące kodu SQL każdego połączenia (zawiera DDL i DML śledzenie oświadczenie)

Ta funkcja jest przeznaczona dla MS SQL Server 2005 \ 2008 , ale będzie działać z MS SQL Server 2000 w ograniczonym zakresie. Ma możliwość nagrywania i raportowania w przychodzącym SQL. Jak korzystać z funkcji: Zobacz

Ujawnienie: Jestem częścią zespołu SQL SPY.

+0

Witryna jest martwa, może stała się: https: // sqlspy. codeplex.com/ - Nie sądzę, że to jednak odpowiada na pytanie. –