Защо не използвате INSTEAD OF
спусък? Изисква малко повече работа (а именно повтаряща се UPDATE
). изявление), но всеки път, когато можете да предотвратите работата, вместо да я оставите да се случи и след това да я върнете обратно, ще бъдете по-добре.
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
Това не пасва идеално. Критериите, които съм пропуснал, са пропуснати по причина:може да е сложно да се определи дали стойността на колона се е променила, тъй като зависи от типа данни, дали колоната може да бъде NULL и т.н. AFAIK вградените тригерни функции може да разбере само дали определена колона е била посочена, а не дали стойността действително се е променила от преди.
РЕДАКТИРАНЕ като се има предвид, че се притеснявате само за другите колони, които се актуализират поради след задействане, мисля, че следното INSTEAD OF
тригерът може да замени и двете ви съществуващи задействания и също така да работи с множество редове, актуализирани наведнъж (някои без да отговарят на вашите критерии):
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