TransactSQL - wyzwalacze

Składnia i zasada działania wyzwalaczy w Oracle i MS SQL Server dość znacznie się różnią. W serwerze Microsoftu wyzwalacz jest zawsze wywoływany po wykonaniu instrukcji. Nie istnieją wyzwalacze typu "before". Nie istnieją również wyzwalacze typu "FOR EACH ROW". Wyzwalacz jest zawsze uruchamiany dla całej instrukcji DML. Odwołania do starych i nowych wartości modyfikowanych danych są możliwe dzięki wirtualnym tabelom o nazwach "inserted" i "deleted", zawierających odpowiednio nowe i stare wartości. Aby się do nich odwołać, musimy użyć instrukcji SELECT tak, jakby były to normalne tabele bazy danych. Modyfikacja danych bezpośrednio w tych tabelach nie jest możliwa. Istnieje możliwość sprawdzenia, jaka kolumna była modyfikowana używając IF UPDATE(nazwa_kolumny). Aby utworzyć wyzwalacz, piszemy:

CREATE TRIGGER nazwa_wyzwalacza
ON tabela
FOR instrukcje
AS
instrukcje Transact-SQL 

Instrukcje, które mogą wywołać wyzwalacz to: INSERT, UPDATE i DELETE. Po słowie FOR możemy napisać jedną, dwie lub wszystkie trzy (oddzielone przecinkami).

W poniższym przykładzie wyzwalacz nie pozwoli usunąć wiersza z tabeli. Ponieważ jednak wyzwalacz jest uruchamiany po wykonaniu operacji DELETE, musimy przy pomocy instrukcji ROLLBACK wycofać wprowadzone zmiany:

CREATE TRIGGER wyzw ON Emp
FOR DELETE
AS
ROLLBACK

W kolejnym przykładzie, chcielibyśmy aby nowo wstawiani pracownicy nie mogli mieć zarobków równych zero. Gdy taki pracownik zostanie wprowadzony, wyzwalacz usunie go i zgłosi błąd:

CREATE TRIGGER wyzw ON Emp
FOR INSERT
AS
DECLARE @sal DECIMAL(6,2)
SELECT @sal = sal FROM inserted
IF @sal = 0
BEGIN
	ROLLBACK
	RAISERROR('Nie można wstawić pracownika z pensją równą zero!',1,2)
END

Składnia instrukcji RAISERROR wygląda następująco:

RAISERROR(message, severity, state)

Gdzie:
Message - dowolny tekst (komunikat błędu)
Severity - liczba z przedziału 0-25 (przy czym użytkownik może używać wartości z przedziału 0-18
State - liczba z przedziału 1-127

Wartości parametrów "severity" i "state" są przekazywane do aplikacji klienta, dzięki czemu różne błędy mogą być obsługiwane w różny sposób.

Rozważmy kolejny przykład. Chcielibyśmy aby przy zwiększeniu pensji, była zerowana prowizja:

CREATE TRIGGER wyzw ON Emp
FOR UPDATE
AS
DECLARE @sal_old DECIMAL(6,2), @sal_new DECIMAL(6,2), @id INT
SELECT @sal_old = sal, @id = Empno FROM deleted
SELECT @sal_new = sal FROM inserted
IF @sal_old < @sal_new
	UPDATE Emp SET Comm = 0 WHERE Empno = @id