更新后触发和批量更新

时间:2010-11-16 17:06:28

标签: sql-server sql-server-2008

我有以下触发器来避免更新某个列。

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表是否可以在触发器范围内包含多行?

...谢谢

2 个答案:

答案 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)

您需要在触发器中定义游标并在游标中获取所有受影响的记录,然后对其进行处理。