Warum nicht einen INSTEAD OF
verwenden Abzug? Es erfordert etwas mehr Arbeit (nämlich ein wiederholtes UPDATE
Anweisung), aber jederzeit, wenn Sie Arbeit verhindern können, werden Sie besser dran sein, anstatt sie geschehen zu lassen und sie dann rückgängig zu machen.
CREATE TRIGGER [dbo].[Item_BeforeUpdate_AnyBilled]
ON [dbo].[Item]
INSTEAD OF UPDATE
AS
BEGIN
SET NOCOUNT ON;
IF EXISTS
(
SELECT 1 FROM inserted i
JOIN deleted AS d ON i.ItemId = d.ItemId
WHERE d.BillId IS NULL -- it was NULL before, may not be NULL now
)
BEGIN
UPDATE src
SET col1 = i.col1 --, ... other columns
ModifiedDate = CURRENT_TIMESTAMP -- this eliminates need for other trigger
FROM dbo.Item AS src
INNER JOIN inserted AS i
ON i.ItemId = src.ItemId
AND (criteria to determine if at least one column has changed);
END
ELSE
BEGIN
RAISERROR(...);
END
END
GO
Das passt nicht perfekt. Die Kriterien, die ich weggelassen habe, werden aus einem bestimmten Grund weggelassen:Es kann komplex sein, festzustellen, ob sich ein Spaltenwert geändert hat, da dies vom Datentyp abhängt, ob die Spalte NULL sein kann usw. AFAIK, die eingebauten Triggerfunktionen kann nur feststellen, ob eine bestimmte Spalte angegeben wurde, nicht, ob sich der Wert tatsächlich geändert hat.
BEARBEITEN Wenn man bedenkt, dass Sie sich nur um die anderen Spalten sorgen, die aufgrund des After-Triggers aktualisiert werden, denke ich, dass das folgende INSTEAD OF
Trigger kann Ihre beiden vorhandenen Trigger ersetzen und auch mehrere Zeilen gleichzeitig aktualisieren (einige ohne Ihre Kriterien zu erfüllen):
CREATE TRIGGER [dbo].[Item_BeforeUpdate_AnyBilled]
ON [dbo].[Item]
INSTEAD OF UPDATE
AS
BEGIN
SET NOCOUNT ON;
UPDATE src SET col1 = i.col1 --, ... other columns,
ModifiedDate = CURRENT_TIMESTAMP
FROM dbo.Item AS src
INNER JOIN inserted AS i
ON src.ItemID = i.ItemID
INNER JOIN deleted AS d
ON i.ItemID = d.ItemID
WHERE d.BillID IS NULL;
IF @@ROWCOUNT = 0
BEGIN
RAISERROR(...);
END
END
GO