inserted
là một bảng giả và nó chắc chắn chứa tất cả các hàng bên phải đã bị ảnh hưởng bởi UPDATE
câu lệnh (và tôi giả sử DISTINCT
không cần thiết, nếu ID
khóa chính - mặc dù rất khó để biết bảng là gì với tên như 121s
). Liệu tất cả chúng thực sự đã thay đổi giá trị là một thứ khác mà bạn có thể cân nhắc xác thực trước khi áp dụng ngày / giờ đã sửa đổi. Bỏ qua điều đó, tôi có thể sẽ làm theo cách này:
ALTER TRIGGER [dbo].[trg_121s]
ON [dbo].[121s]
AFTER UPDATE
AS
BEGIN
SET NOCOUNT ON;
UPDATE t SET modified = CURRENT_TIMESTAMP
FROM dbo.[121s] AS t
WHERE EXISTS (SELECT 1 FROM inserted WHERE ID = t.ID);
-- WHERE EXISTS is same as INNER JOIN inserted AS i ON t.ID = i.ID;
END
GO
Nếu bạn muốn đảm bảo chắc chắn 100% rằng tất cả chúng đều được cập nhật với cùng một dấu thời gian (mặc dù tôi không biết liệu mình đã từng thấy nhiều giá trị trong trường hợp sử dụng này chưa):
ALTER TRIGGER [dbo].[trg_121s]
ON [dbo].[121s]
AFTER UPDATE
AS
BEGIN
SET NOCOUNT ON;
DECLARE @ts DATETIME;
SET @ts = CURRENT_TIMESTAMP;
UPDATE t SET modified = @ts
FROM dbo.[121s] AS t
INNER JOIN inserted AS i
ON t.ID = i.ID;
END
GO
Và nếu bạn muốn đảm bảo rằng cập nhật chỉ xảy ra nếu, giả sử, cột foo
giá trị đã thay đổi, bạn có thể nói:
UPDATE t SET modified = @ts
FROM dbo.[121s] AS t
INNER JOIN inserted AS i
ON t.ID = i.ID
AND t.foo <> i.foo;
Đó là mô hình chung, nhưng nó trở nên phức tạp hơn nếu foo
là nullable, vì SQL Server sẽ không thể đối sánh trên các hàng mà một bên có giá trị và bên kia không (hoặc cả hai đều không). Trong trường hợp đó, bạn sẽ làm điều này:
AND
(
t.foo <> i.foo
OR (t.foo IS NULL AND i.foo IS NOT NULL)
OR (t.foo IS NOT NULL AND i.foo IS NULL)
);
Một số người sẽ nói "Tôi chỉ có thể sử dụng COALESCE hoặc ISNULL để chống lại một số giá trị ma thuật" như thế này:
WHERE COALESCE(t.foo, 'magic') <> COALESCE(i.foo, 'magic')
... và tôi sẽ cảnh báo bạn chống lại điều này, bởi vì bạn sẽ liên tục tìm kiếm một giá trị kỳ diệu nào đó không thể tồn tại trong dữ liệu.