Tại sao không sử dụng INSTEAD OF
cò súng? Nó yêu cầu nhiều công việc hơn một chút (cụ thể là UPDATE
lặp lại tuyên bố) nhưng bất cứ lúc nào bạn có thể ngăn cản công việc, thay vì để nó xảy ra và sau đó quay trở lại, bạn sẽ tốt hơn.
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
Điều này không hoàn toàn phù hợp. Tiêu chí tôi đã bỏ qua bị bỏ qua vì một lý do:có thể phức tạp để xác định xem giá trị cột có thay đổi hay không, vì nó phụ thuộc vào kiểu dữ liệu, liệu cột đó có thể là NULL hay không, v.v. KHẮC PHỤC các hàm kích hoạt tích hợp sẵn chỉ có thể cho biết liệu một cột nhất định đã được chỉ định hay chưa, chứ không phải liệu giá trị có thực sự thay đổi so với trước đó hay không.
CHỈNH SỬA xem xét rằng bạn chỉ quan tâm đến các cột khác được cập nhật do trình kích hoạt sau, tôi nghĩ rằng INSTEAD OF
sau trình kích hoạt có thể thay thế cả hai trình kích hoạt hiện tại của bạn và cũng xử lý nhiều hàng được cập nhật cùng một lúc (một số hàng không đáp ứng tiêu chí của bạn):
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