Uwaga
Dostęp do tej strony wymaga autoryzacji. Może spróbować zalogować się lub zmienić katalogi.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
Dotyczy:SQL Server
Azure SQL Database
Azure SQL Managed Instance
Podczas pisania kodu wyzwalacza DML należy wziąć pod uwagę, że instrukcja, która powoduje wyzwolenie wyzwalacza, może być pojedynczą instrukcją, która ma wpływ na wiele wierszy danych, zamiast jednego wiersza. To zachowanie jest typowe dla wyzwalaczy UPDATE i DELETE, ponieważ te instrukcje często mają wpływ na wiele wierszy. Zachowanie jest mniej powszechne w przypadku wyzwalaczy INSERT, ponieważ podstawowa instrukcja INSERT dodaje tylko jeden wiersz. Jednak ponieważ wyzwalacz INSERT może zostać wyzwolony przez instrukcję INSERT INTO (table_name) SELECT, wstawianie wielu wierszy może spowodować wywołanie pojedynczego wyzwalacza.
Zagadnienia dotyczące wielowierszowego przetwarzania są szczególnie ważne, gdy funkcja wyzwalacza DML polega na automatycznym ponownym obliczaniu wartości podsumowania z jednej tabeli i przechowywaniu wyników w innej tabeli do bieżącego zestawienia.
Notatka
Nie zalecamy używania kursorów w wyzwalaczach, ponieważ mogą one potencjalnie zmniejszyć wydajność. Aby zaprojektować wyzwalacz, który ma wpływ na wiele wierszy, użyj logiki opartej na zestawie wierszy zamiast kursorów.
Przykłady
Wyzwalacze DML w poniższych przykładach zostały zaprojektowane tak, aby przechowywać sumę bieżącą kolumny w innej tabeli przykładowej bazy danych AdventureWorks2022
.
A. Przechowywanie bieżącej sumy podczas wstawiania pojedynczego wiersza
Pierwsza wersja wyzwalacza DML działa dobrze w przypadku wstawiania pojedynczego wiersza, gdy wiersz danych jest ładowany do tabeli PurchaseOrderDetail
. Instrukcja INSERT uruchamia wyzwalacz DML, a nowy wiersz jest ładowany do tabeli wstawionej na czas wykonywania wyzwalacza. Instrukcja UPDATE
odczytuje wartość kolumny LineTotal
dla wiersza i dodaje wartość do istniejącej wartości w kolumnie SubTotal
w tabeli PurchaseOrderHeader
. Klauzula WHERE
zapewnia, że zaktualizowany wiersz w tabeli PurchaseOrderDetail
jest zgodny z PurchaseOrderID
wiersza w tabeli wstawionej.
-- Trigger is valid for single-row inserts.
USE AdventureWorks2022;
GO
CREATE TRIGGER NewPODetail
ON Purchasing.PurchaseOrderDetail
AFTER INSERT AS
UPDATE PurchaseOrderHeader
SET SubTotal = SubTotal + LineTotal
FROM inserted
WHERE PurchaseOrderHeader.PurchaseOrderID = inserted.PurchaseOrderID ;
B. Przechowywanie bieżącej sumy dla wstawienia wielowierszowego lub jednowierszowego
W przypadku wstawiania wielorowowego wyzwalacz DML w przykładzie A może nie działać poprawnie; wyrażenie z prawej strony wyrażenia przypisania w instrukcji UPDATE (SubTotal
+ LineTotal
) może być tylko jedną wartością, a nie listą wartości. W związku z tym efektem wyzwalacza jest pobranie wartości z dowolnego wiersza w tabeli wstawionej i dodanie tej wartości do istniejącej wartości SubTotal
w tabeli PurchaseOrderHeader
dla określonej wartości PurchaseOrderID
. Ta operacja może nie mieć oczekiwanego efektu, jeśli jedna wartość PurchaseOrderID
wystąpiła więcej niż raz w tabeli wstawionej.
Aby poprawnie zaktualizować tabelę PurchaseOrderHeader
, wyzwalacz musi umożliwiać istnienie wielu wierszy w wstawionej tabeli . W tym celu można użyć funkcji SUM
, która oblicza łączną LineTotal
dla grupy wierszy w tabeli wstawionej w dla każdego PurchaseOrderID
. Funkcja SUM
jest uwzględniona w skorelowanym podzapytaniu (instrukcja SELECT
w nawiasach). Ta podzapytywanie zwraca pojedynczą wartość dla każdej PurchaseOrderID
w tabeli wstawionej, która jest zgodna lub jest skorelowana z PurchaseOrderID
w tabeli PurchaseOrderHeader
.
-- Trigger is valid for multirow and single-row inserts.
USE AdventureWorks2022;
GO
CREATE TRIGGER NewPODetail2
ON Purchasing.PurchaseOrderDetail
AFTER INSERT AS
UPDATE Purchasing.PurchaseOrderHeader
SET SubTotal = SubTotal +
(SELECT SUM(LineTotal)
FROM inserted
WHERE PurchaseOrderHeader.PurchaseOrderID
= inserted.PurchaseOrderID)
WHERE PurchaseOrderHeader.PurchaseOrderID IN
(SELECT PurchaseOrderID FROM inserted);
Ten mechanizm wyzwalający działa również poprawnie przy wstawianiu pojedynczego wiersza; suma kolumny wartości LineTotal
jest sumą pojedynczego wiersza. Jednak w przypadku tego wyzwalacza skorelowane podzapytanie i operator IN
używany w klauzuli WHERE
wymagają dodatkowego przetwarzania przez serwer SQL. Nie jest to potrzebne w przypadku wstawiania pojedynczego wiersza.
C. Przechowywanie sumy bieżącej w zależności od typu insertu
Wyzwalacz można zmienić, aby użyć metody optymalnej dla liczby wierszy. Na przykład funkcja @@ROWCOUNT
może służyć w logice wyzwalacza do rozróżnienia między wstawianiem pojedynczego wiersza a wielowierszowym.
-- Trigger valid for multirow and single row inserts
-- and optimal for single row inserts.
USE AdventureWorks2022;
GO
CREATE TRIGGER NewPODetail3
ON Purchasing.PurchaseOrderDetail
FOR INSERT AS
IF @@ROWCOUNT = 1
BEGIN
UPDATE Purchasing.PurchaseOrderHeader
SET SubTotal = SubTotal + LineTotal
FROM inserted
WHERE PurchaseOrderHeader.PurchaseOrderID = inserted.PurchaseOrderID
END
ELSE
BEGIN
UPDATE Purchasing.PurchaseOrderHeader
SET SubTotal = SubTotal +
(SELECT SUM(LineTotal)
FROM inserted
WHERE PurchaseOrderHeader.PurchaseOrderID
= inserted.PurchaseOrderID)
WHERE PurchaseOrderHeader.PurchaseOrderID IN
(SELECT PurchaseOrderID FROM inserted)
END;