Nieodzownym elementem struktury naszej bazy jest fakt jej rozbudowy i rozwoju wraz z pojawiającymi się nowymi procesami czy usprawnianiem obecnych. Zwiększenie liczby obiektów pomagających w automatyzacji tego wszystkiego jest w pewnym momencie olbrzymia. W bazach danych jednym z takich obiektów są triggery (wyzwalacze), które zostaną szerzej omówione w innym artykule.
Często przy pracach technicznych, czyszczeniu danych, bądź nawet naprawianiu skutków błędnej logiki kodu – musimy zaktualizować lub usunąć wadliwe dane. Nie jest to problem, o ile nie mamy wprowadzonych triggerów np. w celach historyzacji zmian rekordów. W przeciwnym razie staniemy przed falą nowych wpisów zawierającymi informację o naszych poczynieniach. Kolejna spora ilość zbędnych danych pojawi się w tabeli i jak najbardziej możemy je po wszystkim usunąć, ale to są kolejne operacje na setkach, jak nie na milionach rekordach.
Możemy uniknąć powyższej sytuacji uprzednio wyłączając triggery odpowiadające za wprowadzanie tychże wpisów. Do tego wystarczy prosta komenda, w której wskażemy który konkretny obiekt chcemy wyłączyć:
DISABLE TRIGGER Sales.PriceChange ON Sales.Prices;
GO
Po zakończeniu prac wykonujemy przeciwną operacja, czyli włączamy wskazany trigger:
ENABLE TRIGGER Sales.PriceChange ON Sales.Prices;
GO
Dzięki temu zabiegowi unikniemy dodatkowej pracy i zaoszczędzimy czas, który przy pracach naprawczych jest dość cennym zasobem. Idąc dalej, jeżeli ktoś zapyta „a co jeżeli mamy więcej wyzwalaczy, to mam je wszystkie pojedynczo wyłączać”?
Oczywiście, że nie musimy, mamy od tego również gotowe polecenie jakim jest:
DISABLE TRIGGER ALL ON ALL SERVER;
GO
Powyższe polecenie możliwe jest do realizacji w obrębie tabeli, widoku, bazy czy serwera. Wystarczy odpowiednio podać nazwę obiektu lub DATABASE/ALL SERVER.
W tym miejscu należałoby spytać, czy faktycznie potrzebujemy wyłączyć wszystkie wyzwalacze na bazie? Nie wystarczy nam na chwilę nie wykonywać wyłącznie historyzacji? Co z pozostałymi poleceniami, które np. chronią nas przed niepożądanymi zmianami poprzez ALTER/UPDATE?
Znacznie wygodniej byłoby wyłączyć tylko część tych obiektów – i to jak najbardziej słusznie! Jeżeli nie musimy to nie róbmy nadprogramowych, niepotrzebnych rzeczy. Zgodnie z zasadą – Im mniej operacji tym lepiej.
Zerknijmy na poniższy skrypt dzięki, któremu możemy wyznaczyć triggery, posługując się ich unikalnymi nazwami lub fragmentem nazw grup. Dodatkowo mamy wybór: czy chcemy wyłączyć, czy włączyć dopasowane wyzwalacze. Jak widać do tego celu do dyspozycji jest jeden z parametrów: @ToggleIsDisabled , należy zmienić jego wartość w zależności od oczekiwań: 1 – wyłączenie, 0 – włączenie
DECLARE @TriggerName varchar(500);
DECLARE @TableName varchar(500);
DECLARE @SchemaName varchar(500);
DECLARE @SQL varchar(max) = NULL;
DECLARE @ToggleIsDisabled INT = 1; -- Wybierz 0-ENABLE/1-DISABLE
DROP TABLE IF EXISTS #trg_list;
SELECT
ROW_NUMBER() OVER (PARTITION BY (SELECT NULL) ORDER BY (SELECT NULL)) AS ID
, T.name AS TriggerName
, O.name AS TableName
, S.name AS SchemaName
, T.is_disabled AS IsDisabled
INTO #trg_list
FROM sys.triggers AS T
INNER JOIN sys.objects AS O
ON T.parent_id = O.object_id
INNER JOIN sys.schemas AS S
ON O.schema_id = S.schema_id
WHERE
T.name LIKE 'HIST_%'; -- tutaj podajemy zgodnie z naszą nomenklaturą
DECLARE @next_id INT = 1;
DECLARE @max_id INT = (SELECT MAX(ID) FROM #trg_list);
DECLARE @operation NVARCHAR(8);
WHILE @next_id < @max_id + 1
BEGIN
SELECT @TriggerName = TriggerName, @TableName = TableName, @SchemaName = SchemaName FROM #trg_list WHERE ID = @next_id
SET @operation = (SELECT CASE WHEN @ToggleIsDisabled = 1 THEN 'DISABLE' WHEN @ToggleIsDisabled = 0 THEN 'ENABLE' END)
SET @SQL = @operation +' TRIGGER ' + @TriggerName + ' ON ' + QUOTENAME(@SchemaName) + '.' + QUOTENAME(@TableName)
EXEC (@SQL)
PRINT '>> Trigger ' + @TriggerName + 'is disabled on ' + @SchemaName + '.' + @TableName
PRINT 'command: ' + @SQL
SET @next_id = @next_id + 1;
END;