Mamy bazę danych SQL Server, która ma specyfikację kontroli bazy danych, która kontroluje wszystkie działania wykonywane w bazie danych.
CREATE DATABASE AUDIT SPECIFICATION [dbAudit]
FOR SERVER AUDIT [servAudit]
ADD (EXECUTE ON DATABASE::[DatabaseName] BY [public])
Odkryliśmy, że niektóre zapytania zapisują w dzienniku kontroli użycie funkcji skalarnej dla każdego wiersza w zestawie wyników. Kiedy tak się dzieje, dziennik zapełnia się, zanim będziemy mogli go ETL umieścić w ostatecznym miejscu spoczynku i mamy luki w logowaniu.
Niestety z powodów zgodności nie możemy po prostu przestać sprawdzać każdego EXECUTE
oświadczenia.
Naszym pierwszym podejściem do rozwiązania tego problemu jest użycie WHERE
klauzuli dotyczącej Audytu serwera w celu odfiltrowania działania. Kod wyglądał następująco:
WHERE [object_id] not in (Select object_id from sys.objects where type = 'FN' )
Niestety, SQL Server nie zezwala na relacyjny operator IN (prawdopodobnie dlatego, że nie chce zapytać za każdym razem, gdy musi zapisywać w dzienniku kontroli).
Chcielibyśmy uniknąć zapisywania przechowywanego proc, który koduje na stałe object_id
w WHERE
klauzuli, ale takie jest nasze obecne podejście do najlepszego rozwiązania tego problemu. Czy istnieje alternatywne podejście, które powinniśmy rozważyć?
Zauważyliśmy, że gdy funkcja skalarna jest używana w rekurencyjnym CTE, powoduje to, że zapytanie zapisuje się w dzienniku kontroli dla każdego wiersza w zestawie wyników.
Niektóre funkcje o wartościach skalarnych są dostarczane przez dostawcę, których nie możemy usunąć ani przenieść do alternatywnej bazy danych.
We've found that some queries will write to the audit log the use of a scalar function for every row in a result set.
- To jeden z najwspanialszych efektów ubocznych skalarnych UDF, jakie kiedykolwiek słyszałem i dużo słyszałem.Odpowiedzi:
Jest kilka opcji, które udało mi się uruchomić. Wszystkie opcje dotyczą odmian predykatów filtrów. UWAGA: należy wyłączyć Audyt serwera, aby wprowadzić zmiany, a następnie włączyć go ponownie .
Po pierwsze, najbardziej ogólnym podejściem jest odfiltrowanie wszystkich skalarnych UDF. Możesz to zrobić za pomocą
class_type
pola audytu. Dokumentacja wskazuje, że to pole jestVARCHAR(2)
, ale nie pozwala na określenie ciągu. Dostałem jednak następujące rzeczy do pracy:(więcej informacji na temat tego dochodzenia tutaj: Tajemnica audytu serwera: Filtrowanie typu_klasa powoduje błąd Msg 25713 )
Następne najbardziej ogólne podejście nie wchodzi w grę, ponieważ stwierdzono, że jest to baza danych dostarczona przez dostawcę i dlatego nie można wprowadzać żadnych zmian. Opiszę to ostatnie.
Najmniej ogólne podejście (ale takie, które zdecydowanie działa) to odfiltrowanie konkretnej nazwy funkcji:
Lub, jeśli wiele nazw:
Chociaż nie jest to bardzo ogólne, podejście to powinno być dobre, ponieważ liczba funkcji do odfiltrowania powinna być dość mała i nie będzie zbyt często, gdy wprowadzane są nowe funkcje.
Wreszcie, dla innych osób, które zmagają się z tą sytuacją i nie są ograniczone do dokonywania zmian: możesz umieścić funkcje we własnym schemacie, a następnie odfiltrować tylko ten schemat. Jest to bardziej ogólne niż oddzielne filtrowanie funkcji. Zakładając, że utworzysz Schemat o nazwie
fn
i umieścisz w nim funkcje:RÓWNIEŻ, w odniesieniu do następujących dwóch komentarzy w pytaniu:
i:
IN
Operator nie jest problemem. To prawda, że nie jest obsługiwane, ale jest tylko skrótem do listyOR
warunków. Rzeczywistym problemem jest użycie T-SQL. Dozwolone są tylko literały - ciągi lub liczby - Więc i tak nie byłbyś w stanie wykonać Procedury składowanej. Nie można także korzystać z wbudowanych funkcji.źródło
=
aby być<>
w mojej odpowiedzi. Właśnie go przetestowałem i działa zgodnie z reklamą :-)