Sqlserver
 sql >> Baza danych >  >> RDS >> Sqlserver

Wyzwalacz SQL Server:zrozumienie i alternatywy

Wyzwalacz programu SQL Server to specjalny typ procedur składowanych, który jest automatycznie wykonywany, gdy zdarzenie wystąpi na określonym serwerze bazy danych. SQL Server udostępnia nam dwa główne typy wyzwalaczy:DML Wyzwalacze i DDL wyzwalacze. Wyzwalacze DDL będą uruchamiane w odpowiedzi na różne zdarzenia języka definicji danych (DDL), takie jak wykonywanie instrukcji T-SQL CREATE, ALTER, DROP, GRANT, DENY i REVOKE. Wyzwalacz DDL może reagować na działania DDL, zapobiegając wpływowi tych zmian na bazę danych, wykonując inne działanie w odpowiedzi na te działania DDL lub rejestrując te zmiany, które są wykonywane w bazie danych.

Wyzwalacz SQL Server DML to specjalny typ procedur składowanych, który jest przeznaczony do wykonywania sekwencji działań na tabeli bazy danych, do której jest dołączony wyzwalacz, gdy zdarzenia Data Manipulation Language (DML), takie jak INSERT, UPDATE lub DELETE akcja, występuje w celu zmodyfikowania zawartości tabel lub widoków bazy danych, niezależnie od tego, czy dotyczy to wierszy tabeli. Wyzwalacze różnią się od procedur składowanych tym, że wyzwalacze są wyzwalane automatycznie po wystąpieniu wstępnie zdefiniowanej modyfikacji danych. Wyzwalacze DML mogą być używane do zachowania integralności danych i egzekwowania reguł biznesowych firmy, tak samo jak funkcja sprawdzania tabeli i ograniczeń kluczy obcych, poprzez wykonywanie procesów audytu i innych działań po DML. Możesz użyć wyzwalaczy DML do wysyłania zapytań do innych tabel i wykonywania złożonych zapytań T-SQL.

Jeśli wyzwalacz zostanie uruchomiony, specjalny rodzaj wirtualnych tabel o nazwie Wstawiono i Usunięte tabele będą używane do przechowywania wartości danych przed i po modyfikacji. Instrukcja wyzwalacza będzie działać w zakresie tej samej transakcji, która uruchamia ten wyzwalacz. Oznacza to, że transakcja nie zostanie całkowicie zatwierdzona, dopóki instrukcja wyzwalacza nie zostanie pomyślnie zakończona. Z drugiej strony transakcja zostanie wycofana, jeśli instrukcja wyzwalacza nie powiedzie się.

Istnieją dwa typy wyzwalaczy DML:PO lub DLA wyzwalacz i ZAMIAST cyngiel. Wyzwalacz AFTER zostanie uruchomiony i wykonany po wykonaniu akcji INSERT, UPDATE lub DELETE, która go pomyślnie uruchomi. Ponadto wszelkie referencyjne akcje kaskadowe i kontrole ograniczeń powinny zakończyć się pomyślnie przed uruchomieniem wyzwalacza. Wyzwalacz AFTER można zdefiniować tylko na poziomie tabeli bez możliwości definiowania go na widokach. Wyzwalacz INSTEAD OF służy do zastąpienia instrukcji akcji, która uruchamia wyzwalacz, instrukcją podaną w wyzwalaczu, wycofując tę ​​instrukcję po zgłoszeniu błędu, gdy ktoś próbuje wykonać akcję, która łamie określoną zasadę, taką jak aktualizacja krytyczna kolumna finansowa lub zapisanie zmiany w tabeli audytu przed wykonaniem zmiany. Wyzwalacz INSTEAD OF umożliwia WSTAWIANIE, AKTUALIZOWANIE lub USUWANIE danych z widoków, które odwołują się do danych z wielu tabel, oprócz możliwości odrzucenia części zapytania wsadowego i pomyślnego wykonania innej części tej partii. Wyzwalacza INSTEAD OF nie można używać z aktualizowalnymi widokami, które mają opcję WITH CHECK OPTION oraz w tabelach z relacją referencyjną, która określa działania kaskadowe na DELETE lub UPDATE.

Po teoretycznym omówieniu wyzwalaczy zaczniemy pokazywać to, o czym mówimy w praktyce. W nadchodzących demonstracjach pokażemy różne sytuacje, w których możemy czerpać korzyści z wyzwalaczy SQL Server.

PO… Wyzwoleniu DML

Załóżmy, że musimy śledzić akcje DML, które są wykonywane na określonej tabeli i zapisywać te logi w tabeli historii, gdzie identyfikator wstawionego, zaktualizowanego lub usuniętego rekordu oraz akcja, która jest wykonywana, zostaną zapisane w tabeli historii. Poniższe instrukcje T-SQL CREATE TABLE mogą służyć do tworzenia zarówno tabel źródłowych, jak i historycznych:

CREATE TABLE TriggerDemo_Parent
(
   ID INT IDENTITY (1,1) PRIMARY KEY,
   Emp_First_name VARCHAR (50),
   Emp_Last_name VARCHAR (50),
   Emp_Salary INT 
  )
GO

CREATE TABLE TriggerDemo_History
(
   ID INT IDENTITY (1,1) PRIMARY KEY,
   ParentID INT,
   PerformedAction VARCHAR (50),
  )
GO

Aby śledzić operację INSERT, utworzymy wyzwalacz DML, który zostanie uruchomiony po wykonaniu operacji INSERT na tabeli nadrzędnej. Ten wyzwalacz pobierze ostatnio wstawioną wartość identyfikatora do tej tabeli nadrzędnej z wirtualnej wstawionej tabeli, jak w poniższej instrukcji T-SQL CREATE TRIGGER:

CREATE TRIGGER AfterInsertTrigger
ON TriggerDemo_Parent
AFTER INSERT
AS
INSERT INTO TriggerDemo_History VALUES ((SELECT TOP 1  inserted.ID FROM inserted), 'Insert')
GO

Śledzenie operacji DELETE można osiągnąć, tworząc wyzwalacz DML, który jest uruchamiany po wykonaniu operacji DELETE w tabeli nadrzędnej. Ponownie wyzwalacz pobierze wartość identyfikatora ostatniego usuniętego rekordu z tej tabeli nadrzędnej z wirtualnej tabeli usuniętej, jak w poniższej instrukcji T-SQL CREATE TRIGGER:

CREATE TRIGGER AfterDeleteTrigger
ON TriggerDemo_Parent
AFTER DELETE
AS
INSERT INTO TriggerDemo_History VALUES ((SELECT TOP 1  deleted.ID FROM deleted), 'Delete')
GO

Na koniec będziemy śledzić również operację UPDATE, tworząc wyzwalacz DML, który zostanie uruchomiony po wykonaniu operacji UPDATE na tabeli nadrzędnej. W ramach tego wyzwalacza pobierzemy ostatnią zaktualizowaną wartość identyfikatora z tej tabeli nadrzędnej z wirtualnej wstawionej tabeli, biorąc pod uwagę, że proces UPDATE jest wykonywany przez usunięcie rekordu i wstawienie nowego rekordu ze zaktualizowanymi wartościami, jak w CREATE TRIGGER Instrukcja T-SQL poniżej:

CREATE TRIGGER AfterUPDATETrigger
ON TriggerDemo_Parent
AFTER UPDATE
AS
INSERT INTO TriggerDemo_History VALUES ((SELECT TOP 1  inserted.ID FROM inserted), 'UPDATE')
GO

Tabele i wyzwalacze są teraz gotowe do naszych testów. Jeśli spróbujesz wstawić nowy rekord do tabeli nadrzędnej za pomocą poniższej instrukcji INSERT INTO T-SQL:

INSERT INTO TriggerDemo_Parent VALUES ('AAA','BBB',500)

Następnie, sprawdzając plan wykonania wygenerowany przez wykonanie poprzedniej instrukcji INSERT, zobaczysz, że zostaną wykonane dwie operacje wstawiania, mające wpływ na dwie tabele; tabela nadrzędna z wartościami określonymi w instrukcji INSERT oraz tabela historii z powodu uruchomienia wyzwalacza AFTER INSERT, jak pokazano w poniższym planie wykonania:

Jest to również jasne, gdy sprawdzasz dane wstawione zarówno do tabeli nadrzędnej, jak i do tabeli historii za pomocą poniższych instrukcji SELECT:

SELECT * FROM TriggerDemo_Parent
GO
SELECT * FROM TriggerDemo_History

Gdzie wartości określone w instrukcji INSERT zostaną wstawione do tabeli nadrzędnej, a dziennik wstawiania zawierający identyfikator wstawionego rekordu i wykonanej operacji zostanie wstawiony do tabeli historii, jak pokazano w poniższym wyniku:

Teraz, jeśli spróbujesz zaktualizować istniejący rekord w tabeli nadrzędnej za pomocą poniższej instrukcji UPDATE T-SQL:

UPDATE TriggerDemo_Parent SET Emp_Salary=550 WHERE ID=1

I sprawdź plan wykonania wygenerowany przez wykonanie poprzedniej instrukcji UPDATE, zobaczysz, że po operacji aktualizacji nastąpi operacja wstawiania mająca wpływ na dwie różne tabele; tabela nadrzędna zostanie zaktualizowana o wartość określoną w instrukcji UPDATE i operacja wstawienia do tabeli historii z powodu uruchomienia wyzwalacza AFTER UPDATE, jak pokazano w poniższym planie wykonania:

Sprawdzanie zarówno rekordów nadrzędnych, jak i tabeli historii za pomocą poniższych instrukcji SELECT:

SELECT * FROM TriggerDemo_Parent
GO
SELECT * FROM TriggerDemo_History

Zobaczysz, że instrukcja aktualizacji zmodyfikuje wartość Emp_Salary w tabeli nadrzędnej o wartość określoną w instrukcji UPDATE, a dziennik aktualizacji zawierający identyfikator zaktualizowanego rekordu i wykonanej operacji zostanie wstawiony do tabeli historii, ponieważ pokazane w poniższym wyniku:

W ostatnim scenariuszu wyzwalacza AFTER DML będziemy śledzić usuwanie istniejącego rekordu z tabeli nadrzędnej za pomocą poniższej instrukcji DELETE T-SQL:

DELETE FROM  TriggerDemo_Parent WHERE ID=1

Następnie sprawdź plan wykonania wygenerowany przez wykonanie poprzedniej instrukcji DELETE, zobaczysz, że po operacji DELETE nastąpi operacja wstawiania, wpływając na dwie różne tabele; tabela nadrzędna, z której zostanie usunięty rekord z podanym identyfikatorem w klauzuli WHERE instrukcji DELETE oraz operacja wstawiania do tabeli historii w wyniku uruchomienia wyzwalacza AFTER DELETE, jak pokazano w poniższym planie wykonania:

Jeśli sprawdzisz zarówno rekord nadrzędny, jak i tabelę historii za pomocą poniższych instrukcji SELECT:

SELECT * FROM TriggerDemo_Parent
GO
SELECT * FROM TriggerDemo_History

Zobaczysz, że rekord o wartości ID równym 1 został usunięty z tabeli nadrzędnej podanej w instrukcji DELETE, a dziennik usuwania zawierający identyfikator usuniętego rekordu i wykonanej operacji zostanie wstawiony do tabeli historii , jak pokazano w poniższym wyniku:

ZAMIAST… Wyzwalacza DML

Drugim typem wyzwalaczy DML jest wyzwalacz ZAMIAST DML. Jak wspomniano wcześniej, wyzwalacz INSTEAD OF zastąpi instrukcję akcji, która uruchamia wyzwalacz, instrukcją podaną w wyzwalaczu. Załóżmy, że musimy rejestrować akcje DML, które użytkownicy próbują wykonać na określonej tabeli, bez zezwalania im na wykonanie tej akcji. Poniższe instrukcje T-SQL CREATE TABLE mogą służyć do tworzenia tabel źródłowych i alternatywnych:

CREATE TABLE TriggerDemo_NewParent
(
   ID INT IDENTITY (1,1) PRIMARY KEY,
   Emp_First_name VARCHAR (50),
   Emp_Last_name VARCHAR (50),
   Emp_Salary INT 
  )
GO


CREATE TABLE TriggerDemo_InsteadParent
(
   ID INT IDENTITY (1,1) PRIMARY KEY,
   ParentID INT,
   PerformedAction VARCHAR (50),
  )
GO

Po utworzeniu dwóch tabel wstawimy pojedynczy rekord do tabeli źródłowej dla naszego demo za pomocą poniższej instrukcji INSERT INTO:

INSERT INTO TriggerDemo_NewParent VALUES ('AA','BB', 500)

W tym demo utworzymy trzy wyzwalacze zastępujące operacje INSERT, UPDATE i DELETE. Pierwszy wyzwalacz zostanie użyty, aby uniemożliwić jakąkolwiek operację wstawiania w tabeli nadrzędnej i dzienniku, który zmienia się w tabelę alternatywną. Wyzwalacz jest tworzony za pomocą poniższej instrukcji T-SQL CREATE TRIGGER:

CREATE TRIGGER InsteadOfInsertTrigger
ON TriggerDemo_NewParent
INSTEAD OF INSERT
AS
INSERT INTO TriggerDemo_InsteadParent VALUES ((SELECT TOP 1  inserted.ID FROM inserted), 'Trying to Insert new ID')
GO

Drugi wyzwalacz służy do uniemożliwienia jakiejkolwiek operacji aktualizacji w tabeli nadrzędnej i dzienniku, które zmieniają się w tabelę alternatywną. Ten wyzwalacz jest tworzony jak poniżej:

CREATE TRIGGER InsteadOfUpdateTrigger
ON TriggerDemo_NewParent
INSTEAD OF UPDATE
AS
INSERT INTO TriggerDemo_InsteadParent VALUES ((SELECT TOP 1  inserted.ID FROM inserted), 'Trying to Update an existing ID')
GO

Ostatni wyzwalacz zostanie użyty, aby uniemożliwić jakąkolwiek operację usuwania w tabeli nadrzędnej i dzienniku, które zmieniają się w tabelę alternatywną. Ten wyzwalacz jest tworzony w następujący sposób:

CREATE TRIGGER InsteadOfDeleteTrigger
ON TriggerDemo_NewParent
INSTEAD OF DELETE
AS
INSERT INTO TriggerDemo_InsteadParent VALUES ((SELECT TOP 1  inserted.ID FROM inserted), 'Trying to Delete an existing ID')
GO

Dwie tabele i trzy wyzwalacze są już gotowe. Jeśli spróbujesz wstawić nową wartość do tabeli nadrzędnej za pomocą poniższej instrukcji INSERT INTO T-SQL:

INSERT INTO TriggerDemo_NewParent VALUES ('CCC','DDD',500)

Następnie sprawdź zarówno nadrzędną, jak i alternatywną tabelę, używając poniższych instrukcji SELECT:

SELECT * FROM TriggerDemo_NewParent
GO
SELECT * FROM TriggerDemo_InsteadParent

Z uwagi na to, że mamy wyzwalacz INSTEAD OF INSERT w tabeli nadrzędnej, z wyniku widać, że do tabeli nadrzędnej nie jest wstawiany żaden nowy rekord, a do tabeli alternatywnej wstawiany jest dziennik operacji wstawiania, jak pokazano w wyniku poniżej:

Próba aktualizacji istniejącego rekordu w tabeli nadrzędnej za pomocą poniższej instrukcji UPDATE T-SQL:

UPDATE TriggerDemo_NewParent SET Emp_Salary=550 WHERE ID=1

Następnie sprawdź zarówno nadrzędną, jak i alternatywną tabelę, używając poniższych instrukcji SELECT:

SELECT * FROM TriggerDemo_NewParent
GO
SELECT * FROM TriggerDemo_InsteadParent

Z wyniku zobaczysz, że wartość Emp_Salary rekordu o wartości ID równej 1 z tabeli nadrzędnej nie zostanie zmieniona, a dziennik operacji aktualizacji zostanie wstawiony do tabeli alternatywnej ze względu na posiadanie wyzwalacza INSTEAD OF UPDATE w tabeli nadrzędnej, jak pokazano w poniższym wyniku:

Na koniec, jeśli spróbujemy usunąć istniejący rekord z tabeli nadrzędnej za pomocą poniższej instrukcji DELETE T-SQL:

DELETE FROM  TriggerDemo_NewParent  WHERE ID=1

I sprawdź zarówno rekordy tabeli nadrzędnej, jak i alternatywnej, używając poniższych instrukcji SELECT:

SELECT * FROM TriggerDemo_NewParent
GO
SELECT * FROM TriggerDemo_InsteadParent

Z wyniku będzie jasne, że rekord o wartości ID równej 1 z tabeli nadrzędnej nie zostanie usunięty, a log dla operacji usunięcia zostanie wstawiony do tabeli alternatywnej ze względu na posiadanie wyzwalacza INSTEAD OF DELETE w macierzystej tabela, jak pokazano w poniższym wyniku:

PO… Wyzwalanie DML z komunikatami

Wyzwalacz AFTER może być również użyty do wywołania komunikatu ostrzegawczego dla użytkownika. W takim przypadku zapytanie będzie komunikatem informacyjnym, który nie przeszkodzi w wykonaniu instrukcji uruchamiającej ten wyzwalacz. Usuńmy wcześniej utworzony wyzwalacz INSTEAD OF UPDATE i zastąpmy go innym wyzwalaczem AFTER UPDATE, który zgłosi błąd ostrzeżenia po wykonaniu dowolnej operacji aktualizacji przy użyciu poniższych instrukcji T-SQL DROP/CREATE TRIGGER:

DROP TRIGGER InsteadOfUpdateTrigger
CREATE TRIGGER ReminderTrigger  
ON TriggerDemo_NewParent  
AFTER  UPDATE   
AS RAISERROR ('An Update is performed on the TriggerDemo_NewParent table', 16, 10);  
GO  

Jeśli spróbujesz zaktualizować wartość Emp_Salary pracownika o wartości identyfikatora równej 1 za pomocą poniższego oświadczenia UDPATE:

UPDATE TriggerDemo_NewParent SET Emp_Salary=550 WHERE ID=1

Komunikat o błędzie zostanie podniesiony w Wiadomościach zakładka, która zawiera wiadomość podaną w utworzonym wyzwalaczu, jak pokazano poniżej:

Sprawdzanie danych tabeli nadrzędnej za pomocą poniższej instrukcji SELECT:

SELECT * FROM TriggerDemo_NewParent

Na podstawie wyniku zobaczysz, że Emp_Salary zostało pomyślnie zaktualizowane, jak pokazano poniżej:

Jeśli potrzebujesz wyzwalacza AFTER UPDATE, aby zatrzymać operację aktualizacji po zgłoszeniu komunikatu o błędzie, ROLLBACK Instrukcja może zostać dodana do wyzwalacza w celu wycofania operacji aktualizacji, która uruchomiła ten wyzwalacz, przypominając, że wyzwalacz i instrukcja wyzwalająca wyzwalacz zostaną wykonane w tej samej transakcji. Można to osiągnąć za pomocą instrukcji T-SQL ALTER TRIGGER, patrz:

ALTER TRIGGER ReminderTrigger  
ON TriggerDemo_NewParent  
AFTER  UPDATE   
AS RAISERROR ('An Update is performed on the TriggerDemo_NewParent table', 16, 10);  
ROLLBACK
GO  

Jeśli spróbujesz zaktualizować wartość Emp_Salary pracownika o identyfikatorze równym 1, korzystając z poniższej instrukcji UPDATE:

UPDATE TriggerDemo_NewParent SET Emp_Salary=700 WHERE ID=1

Ponownie komunikat o błędzie zostanie wyświetlony w Wiadomościach zakładka, ale tym razem operacja aktualizacji zostanie całkowicie wycofana, jak pokazano w poniższych komunikatach o błędach:

Sprawdzanie wartości z tabeli źródłowej za pomocą poniższej instrukcji SELECT:

SELECT * FROM TriggerDemo_NewParent

Zobaczysz, że wartość Emp_Salary nie uległa zmianie, ponieważ wyzwalacz AFTER UPDATE wycofał całą transakcję po zgłoszeniu komunikatu o błędzie, jak pokazano w tabeli poniżej:

Wady wyzwalania

Przy wszystkich wymienionych zaletach wyzwalaczy SQL Server wyzwalacze zwiększają złożoność bazy danych. Jeśli wyzwalacz jest źle zaprojektowany lub nadużywany, doprowadzi to do poważnych problemów z wydajnością, takich jak zablokowane sesje, z powodu wydłużenia żywotności transakcji na dłuższy czas, dodatkowe obciążenie systemu z powodu wykonywania go za każdym razem, gdy INSERT, UPDATE lub Wykonywana jest akcja DELETE lub może to prowadzić do problemów z utratą danych. Ponadto przeglądanie i śledzenie wyzwalaczy bazy danych nie jest łatwe, zwłaszcza jeśli nie ma na ten temat dokumentacji, ponieważ jest to niewidoczne dla programistów i aplikacji.

Wyzwalanie alternatyw… Wymuszaj uczciwość

Jeśli okaże się, że wyzwalacze obniżają wydajność instancji SQL Server, należy je zastąpić innymi rozwiązaniami. Na przykład zamiast używać wyzwalaczy do wymuszania integralności jednostki, należy ją wymuszać na najniższym poziomie przy użyciu ograniczeń klucza podstawowego i UNIQUE. To samo dotyczy integralności domeny, która powinna być wymuszana przez ograniczenia CHECK, oraz integralności referencyjnej, która powinna być wymuszana przez ograniczenia klucza OBCEGO. Wyzwalaczy DML można używać tylko wtedy, gdy funkcje obsługiwane przez określone ograniczenie nie spełniają wymagań aplikacji.

Porównajmy wymuszanie integralności domeny za pomocą wyzwalaczy DML z ograniczeniami CHECK. Załóżmy, że musimy wymusić wstawianie wartości dodatnich tylko do kolumny Emp_Salary. Zaczniemy od utworzenia prostej tabeli za pomocą poniższej instrukcji T-SQL CREATE TABLE:

CREATE TABLE EmployeeSalaryTrigger
(
   ID INT IDENTITY (1,1) PRIMARY KEY,
   Emp_First_name VARCHAR (50),
   Emp_Last_name VARCHAR (50),
   Emp_Salary INT 
  )
GO

Następnie zdefiniuj wyzwalacz AFTER INSERT DML, który zapewni wstawienie dodatniej wartości do kolumny Emp_Salary przez wycofanie transakcji, jeśli użytkownik wstawi ujemną wartość wynagrodzenia, korzystając z poniższej instrukcji T-SQL CREATE TRIGGER:

CREATE TRIGGER TRGR_EmployeeSalary ON EmployeeSalaryTrigger 
AFTER INSERT 
AS
DECLARE @EmpSal AS INT
SET @EmpSal = (SELECT TOP 1 inserted.Emp_Salary FROM inserted)
IF @EmpSal<0
BEGIN 
 RAISERROR  ('Cannot insert negative salary',16,10);
  ROLLBACK
END

Dla celów porównawczych utworzymy kolejną prostą tabelę o tym samym schemacie i zdefiniujemy ograniczenie CHECK w instrukcji CREATE TABLE, aby akceptować tylko dodatnie wartości w kolumnie Emp_Salary, jak pokazano poniżej:

CREATE TABLE EmployeeSalaryConstraint
(
   ID INT IDENTITY (1,1) PRIMARY KEY,
   Emp_First_name VARCHAR (50),
   Emp_Last_name VARCHAR (50),
   Emp_Salary INT CONSTRAINT EmpSal CHECK (Emp_Salary >=0)
  )
GO

Jeśli spróbujesz wstawić poniższy rekord zawierający ujemną wartość Emp_Salary do pierwszej tabeli ze wstępnie zdefiniowanym wyzwalaczem, używając poniższej instrukcji INSERT INTO:

INSERT INTO EmployeeSalaryTrigger VALUES('Ali', 'Fadi',-4)
GO

Instrukcja INSERT nie powiedzie się, wyświetlając komunikat o błędzie pokazujący, że nie można wstawić wartości ujemnej do kolumny Emp_Salary i wycofać całej transakcji z powodu wyzwalacza AFTER INSERT, jak pokazano w poniższym komunikacie o błędzie:

Ponadto, jeśli spróbujesz wstawić ten sam rekord, który zawiera ujemną wartość Emp_Salary do drugiej tabeli, która ma predefiniowane ograniczenie CHECK, używając poniższej instrukcji INSERT INTO:

INSERT INTO EmployeeSalaryConstraint VALUES ('Ali', 'Fadi',-4)

Instrukcja INSERT ponownie nie powiedzie się, pokazując, że próbujesz wstawić wartość, która jest w konflikcie z warunkiem ograniczenia CHECK, jak pokazano w poniższym komunikacie o błędzie:

Z poprzednich wyników widać, że zarówno wyzwalacz, jak i metody ograniczenia CHECK osiągają cel, uniemożliwiając wstawianie ujemnych wartości Emp_Salary. Ale który z nich jest lepszy? Porównajmy wydajność obu metod, sprawdzając wagę planu wykonania dla każdej z nich. Z wygenerowanych planów wykonania po wykonaniu dwóch zapytań zobaczysz, że waga metody wyzwalacza wynosi trzy razy waga metody ograniczenia CHECK, jak pokazano w porównaniu planu wykonania poniżej:

Ponadto, aby porównać czas wykonywania każdego z nich, uruchommy każdy z nich 1000 razy, używając poniższych instrukcji T-SQL:

INSERT INTO EmployeeSalaryTrigger VALUES('Ali', 'Fadi',-4)
GO 10000  
INSERT INTO EmployeeSalaryConstraint VALUES ('Ali', 'Fadi',-4)
GO 10000 

Zobaczysz, że pierwsza metoda używająca wyzwalacza zajmie około 31 ms do całkowitego wykonania, gdzie druga metoda, która używa ograniczenia CHECK, zajmie tylko 17ms , czyli około 0,5 raza wymagane w metodzie wykorzystującej wyzwalacz. Wynika to z faktu, że wyzwalacz wydłuży czas życia transakcji i wycofuje zapytanie, które uruchamia wyzwalacz po jego wykonaniu, gdy zostanie znalezione naruszenie integralności, powodując pogorszenie wydajności z powodu procesu wycofywania. Inaczej jest w przypadku użycia ograniczenia CHECK, gdzie ograniczenie wykona swoje zadanie przed dokonaniem jakiejkolwiek modyfikacji danych, nie wymagając cofnięcia w przypadku naruszenia.

Wyzwalanie alternatyw… Audyt

Jak wspomnieliśmy wcześniej, wyzwalacze mogą być również używane do audytu i śledzenia zmian dokonywanych w określonej tabeli. Jeśli ta metoda inspekcji powoduje pogorszenie wydajności w Twojej instancji SQL Server, możesz łatwo zastąpić ją WYJŚCIEM klauzula. Klauzula OUTPUT zwraca informacje o każdym wierszu, którego dotyczy operacja INSERT, UPDATE lub DELETE, w postaci komunikatu potwierdzającego lub wartości, którą można wstawić do tabeli historycznej. Metoda klauzuli OUTPUT zapewnia nam również większą kontrolę nad wykonywanym kodem, ponieważ zostanie on dodany do samej instrukcji wstawiania, modyfikacji lub usuwania danych, kiedy tylko zechcesz, w przeciwieństwie do wyzwalacza, który będzie zawsze wykonywany.

Porównajmy logowanie wstawiania i modyfikacji danych do tabeli historii za pomocą wyzwalaczy DML i za pomocą klauzuli OUTPUT. Zaczniemy od utworzenia poniższych tabel produkcyjnych i historycznych za pomocą poniższej instrukcji T-SQL CREATE TABLE:

CREATE TABLE TriggerDemo_Prod
(
   ID INT IDENTITY (1,1) PRIMARY KEY,
   Emp_First_name VARCHAR (50),
   Emp_Last_name VARCHAR (50),
   Emp_Salary INT 
  )
GO


CREATE TABLE TriggerDemo_ProdHistory
(
   ID INT IDENTITY (1,1) PRIMARY KEY,
   ProdID INT,
   ProdSalary INT,
   TS DATETIME,
  )
GO

Po pomyślnym utworzeniu obu tabel utworzymy wyzwalacz PO INSERT, UPDATE DML, który zapisze rekord do tabeli historii, jeśli nowy wiersz zostanie wstawiony do tabeli produkcyjnej lub istniejący rekord zostanie zmodyfikowany za pomocą instrukcji T-SQL CREATE TRIGGER poniżej:

CREATE TRIGGER ProdHistory
ON TriggerDemo_Prod
AFTER INSERT, UPDATE
AS
INSERT INTO TriggerDemo_ProdHistory  VALUES ( (SELECT TOP 1  inserted.ID FROM inserted),(SELECT TOP 1  inserted.Emp_Salary FROM inserted), GETDATE())
GO

Aby porównać rejestrowanie zmian za pomocą metody wyzwalacza i klauzuli OUTPUT, musimy utworzyć dwie nowe proste tabele, tabele produkcyjne i tabele historyczne, o tym samym schemacie, co poprzednie dwie tabele, ale tym razem bez definiowania wyzwalacza, za pomocą Poniższe instrukcje T-SQL CREATE TABLE:

CREATE TABLE OutputDemo_Prod
(
   ID INT IDENTITY (1,1) PRIMARY KEY,
   Emp_First_name VARCHAR (50),
   Emp_Last_name VARCHAR (50),
   Emp_Salary INT 
  )
GO


CREATE TABLE OutputDemo_ProdHistory
(
   ID INT IDENTITY (1,1) PRIMARY KEY,
   ProdID INT,
   ProdSalary INT,
   TS DATETIME,
  )
  
GO

Teraz cztery stoły są gotowe do testów. Wstawimy jeden rekord do pierwszej tabeli produkcyjnej, która ma wyzwalacz za pomocą poniższej instrukcji INSERT INTO T-SQL:

INSERT INTO TriggerDemo_Prod values('AA','BB', 750)
GO 

Następnie wstawimy ten sam rekord do drugiej tabeli produkcyjnej za pomocą klauzuli OUTPUT. Poniższa instrukcja INSERT INTO będzie działać jako dwie instrukcje INSERT; pierwsza wstawi ten sam rekord do tabeli produkcyjnej, a druga instrukcja insert obok klauzuli OUTPUT wstawi dziennik wstawiania do tabeli historii:

INSERT INTO OutputDemo_Prod  OUTPUT inserted.ID, inserted.Emp_Salary, GETDATE() 
INTO OutputDemo_ProdHistory	values('AA','BB', 750)
GO 

Sprawdzając dane wstawione do czterech tabel produkcji i historii, zobaczysz, że obie metody, wyzwalacza i metody OUTPUT, z powodzeniem zapiszą ten sam log do tabeli historii i w ten sam sposób, jak pokazano w poniższym wyniku:

Z wygenerowanych planów wykonania po wykonaniu dwóch zapytań zobaczysz, że waga metody wyzwalacza wynosi około (21%+36%) 57% całkowitej wagi, gdzie waga metody OUTPUT wynosi około 43% , z niewielką różnicą wagi, jak pokazano w porównaniu planów wykonania poniżej:

Różnica wydajności jest wyraźna, gdy porównuje się czas wykonania zużywany przez każdą metodę, gdzie rejestrowanie zmian przy użyciu metody wyzwalacza zajmie (114+125) 239 ms do całkowitego wykonania, a metoda używająca metody klauzuli OUTPUT zużywa tylko 5 ms , czyli 2% czasu użytego w metodzie wyzwalania, jak pokazano w poniższych statystykach czasu:

Z poprzedniego wyniku jasno wynika, że ​​użycie metody OUTPUT jest lepsze niż użycie wyzwalaczy do audytu zmian.

Przydatne linki:

  • CREATE TRIGGER (Transact-SQL) https://docs.microsoft.com/en-us/sql/t-sql/statements/create-trigger-transact-sql
  • Wyzwalacze DML https://docs.microsoft.com/en-us/sql/relational-databases/triggers/dml-triggers
  • Wyzwalacze DDL https://docs.microsoft.com/en-us/sql/relational-databases/triggers/ddl-triggers
  • Klauzula OUTPUT (język Transact-SQL) https://docs.microsoft.com/en-us/sql/t-sql/queries/output-clause-transact-sql

  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Ułatw wydajność SQL Server

  2. Lepsze techniki przycinania wiodących zer w SQL Server?

  3. Uruchamianie programu SQL Server 2014 na maszynie wirtualnej platformy Azure

  4. Kiedy powinienem używać zmiennej tabeli a tabeli tymczasowej w serwerze sql?

  5. Pakiet SSIS nie chce pobierać metadanych tabeli tymczasowej