2017-01-17 38 views
5

Zrozumienie operatorów powodujących efekt uboczny (takich jak "wstawianie") jest zabronione w funkcjach zdefiniowanych przez użytkownika, w jaki sposób jeden dziennik (lub inaczej śledzenie) wywołuje określonego użytkownika -definiowana funkcja? Chciałbym również uchwycić parametry przekazane do UDF.Śledzenie lub rejestrowanie wywołań funkcji zdefiniowanej przez użytkownika w SQL Server

W idealnym przypadku dziennik byłby tabelą, do której wstawione są informacje (sygnatura czasowa i wartości parametrów) o każdym wywołaniu do UDF. Raporty i dane o użyciu mogą być następnie wyprowadzone z tej tabeli.

Nie mogę przepisać UDF jako procedury przechowywanej, nawet o tej samej nazwie, bez łamania wielu systemów niższego rzędu, które znajdują się w środowisku naturalnym, które oczekują UDF i na które nie mam wpływu.

Nie chcę również włączać żadnych funkcji powłoki poleceń na naszym serwerze, które zmniejszą domyślne ustawienia zabezpieczeń SQL Server.

+0

nie powinno być patrząc na SQL Server Profiler do tego? –

+3

@PanagiotisKanavos Nie polecałbym profilera w ogóle. Śledzenie, być może, lub jeszcze lepsze, rozszerzone wydarzenia lub audyt. Profiler jest odpowiedni do lokalnego debugowania, ale absolutnie nie powinien być używany przeciwko systemom produkcyjnym. MOIM ZDANIEM. –

+1

Czy możesz wyjaśnić * dlaczego * chcesz rejestrować wszystkie połączenia z funkcjami zdefiniowanymi przez użytkownika? Nie wpłynie to na odpowiedzi (cóż, nie sądzę), staram się tylko zrozumieć, co możesz na tym zyskać. –

Odpowiedz

1

Można spróbować wykonać następujące czynności:

1) użycie SQL Profiler sprawdzić złowione danych dla każdego z różnych scenariuszy

Sprawdź SP:StmtCompleted aby złapać wypowiedzi, które realizują w ramach procedury przechowywanej lub używane zdefiniowane funkcje. Upewnij się, że uwzględniono wszystkie wymagane kolumny (TextData, LoginName, ApplicationName itd.). TextData jest niezbędne dla tego rozwiązania.

2) Sprawdź każdy scenariusz, aby zobaczyć, co otrzymujesz w profilerze. Np:

-- a mock function that is similar to what I have understood your function does 
alter FUNCTION dbo.GetLoginResult(@username VARCHAR(64)) 
    RETURNS INT 
AS 
BEGIN 
    DECLARE @l INT = LEN(@username) 

    IF (@l < 10) 
     RETURN 0 

    RETURN 1 

    -- DECLARE @Result INT 
    -- SELECT @Result = DATEPART(s, GETDATE()) % 3 
    -- RETURN @Result 
END 
go 

select dbo.GetLoginResult('SomeGuy') --> `IF (@l < 10)` and `RETURN 0` 
GO 

select dbo.GetLoginResult('Some girl with a long name') --> `IF (@l < 10)` and `RETURN 1` 
GO 

Tak więc, jeśli można dostosować swoją funkcję, aby być napisane w taki sposób, że konkretna instrukcja jest wykonywana, gdy dana produkcja ma być zwrócony, można rozpoznać, co jest wynikiem z funkcja oparta na profilowanej informacji (jako wartości wejściowych i wyjściowych nie wydają się być złapany w profilera)

3) po stronie serwera śledzenia

Jak już sugeruje, SQL Profiler stawia znaczny narzut, więc powinien używać śledzenia po stronie serwera. Luckly można eksportować tylko stworzył profilowania informacji wskazanych here:

i) SQL Profiler -> File -> Export -> Script nazwiska Definicja -> Dla SQL Server ..

ii) Wymienić ścieżka w wygenerowany skrypt i uruchom go -> pamiętaj wygenerowany identyfikator (to jest identyfikator śledzenia)

iii) możesz otworzyć plik w programie profilującym i wyeksportować jego dane do tabeli, po zatrzymaniu śledzenia (jest zablokowany przez proces sqlserver) .

10

Znalazłem rozwiązanie twojego problemu. To trochę trudne i wygląda na włamanie, ale wydaje się, że nie da się go rozwiązać w inny sposób.

Chodzi o to, aby utworzyć funkcję SQL .NET, która loguje dane tam, gdzie są potrzebne (plik, dziennik zdarzeń Windows, db itp.), Następnie utwórz moduł UDF SQL, który wywołuje tę funkcję .NET, a następnie wywołaj tę funkcję SQL funkcje przechodzące wszystkie parametry potrzebne do zalogowania. SQL Server nie sprawdza, co jest wewnątrz funkcji .net i możesz tam napisać całą logikę, której potrzebujesz.

Pomysł utworzenia funkcji SQL .net bez żadnych ograniczeń bezpieczeństwa jest brany z tego post.

więc stworzyć projekt NET z tego jednego pliku

using System; 

namespace SqlTest 
{ 
public class LogEvent 
{ 
    [Microsoft.SqlServer.Server.SqlFunction] 
    public static int Log(string data) 
    { 
     System.IO.File.AppendAllText(@"C:\Log\LogUDF.txt", data); 
     return 0; 
    } 
} 
} 

podpisać z jakiegoś certyfikatu pfx (Project Properties -> zakładka podpisania).

Następnie nazwać tego zapytania

USE [master] 
CREATE ASYMMETRIC KEY LogKey FROM EXECUTABLE FILE = 
'C:\Work\ConsoleApplication1\SqlTest\bin\Debug\SqlTest.dll' 

CREATE LOGIN LogLogin FROM ASYMMETRIC KEY LogKey 

GRANT UNSAFE ASSEMBLY TO LogLogin 
GO 

USE [MyDB] 
CREATE ASSEMBLY SqlTest FROM 
'C:\Work\ConsoleApplication1\SqlTest\bin\Debug\SqlTest.dll' 
WITH PERMISSION_SET = unsafe 
GO 
CREATE FUNCTION dbo.Log(@data as nvarchar(200)) 
RETURNS int 
AS EXTERNAL NAME SqlTest.[SqlTest.LogEvent].Log 

Tu trzeba zmienić ścieżkę do skompilowanej biblioteki MojaBD - nazwy bazy danych. I utworzysz funkcję dbo.Log SQL. Następnie możesz zadzwonić tam, gdzie potrzebujesz. Na przykład jak z tego TestFunction

CREATE FUNCTION TestFunction 
(
    @p1 int 
) 
RETURNS int 
AS 
BEGIN 
    DECLARE @temp int 
    SELECT @temp = [dbo].[Log] ('fff') 
    RETURN 1 
END 

Więc, nazywając SELECT TestFunction(1) napisze 'fff' tekst C:\Log\LogUDF.txt pliku.

To wszystko. Kilka ważnych uwag:

  1. Serwer SQL powinien mieć uprawnienia (login/użytkownik) do zapisu w pliku C:\Log\LogUDF.txt.
  2. Trzeba mieć SQL Server Administrator
+0

Doskonała odpowiedź, @Vasyl. Zajęło mi trochę czasu, aby przejść przez to, ale zapewniłeś wszystko, co było mi potrzebne do wykonania zadania. –