我有以下触发器来避免更新某个列。
ALTER TRIGGER [dbo].[MyTrigger]
ON [dbo].[MyTable]
AFTER UPDATE
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
IF UPDATE(SomeID)
BEGIN
DECLARE @id INT,
@newSomeID INT,
@currentSomeID INT
SELECT @id = ID, @newSomeID = SomeID
FROM inserted
SELECT @currentSomeID = SomeID
FROM deleted
WHERE ID = @id
IF (@newSomeID <> @currentSomeID)
BEGIN
RAISERROR ('cannot change SomeID (source = [MyTrigger])', 16, 1)
ROLLBACK TRAN
END
RETURN
END
END
由于我从插入和删除中选择,如果有人使用封装多行的where子句更新表,这是否可行?换句话说,insert和deleted表是否可以在触发器范围内包含多行?
...谢谢
答案 0 :(得分:4)
为什么不使用而不是更新触发器,只是加入INSERTED并推入除你不想更新的列之外的所有列?您的方法不会考虑单个UPDATE语句可能会影响多行。
尝试这样的事情:
ALTER TRIGGER [dbo].[MyTrigger]
ON [dbo].[MyTable]
INSTEAD OF UPDATE
AS
BEGIN
UPDATE m
SET col1=INSERTED.col1
,col2=INSERTED.col2
,col4=INSERTED.col4
FROM [dbo].[MyTable] m
INNER JOIN INSERTED i ON m.PK=i.PK
END
你也可以尝试这样的事情:
ALTER TRIGGER [dbo].[MyTrigger]
ON [dbo].[MyTable]
AFTER UPDATE
AS
BEGIN
IF EXISTS(SELECT 1 FROM INSERTED i INNER JOIN DELETED d ON i.PK=d.PK WHERE i.SomeID!=d.SomeID OR (i.SomeID IS NULL AND d.SomeID IS NOT NULL) OR (d.SomeID IS NULL AND i.SomeID IS NOT NULL))
BEGIN
RAISERROR ('cannot change SomeID (source = [MyTrigger])', 16, 1)
ROLLBACK TRAN
RETURN
END
END
这适用于多行更新。此外,如果“SomeID”为非NULL,您可以删除OR
IF EXISTS
条件
答案 1 :(得分:0)
您需要在触发器中定义游标并在游标中获取所有受影响的记录,然后对其进行处理。