代码之家  ›  专栏  ›  技术社区  ›  Jonas Stawski

更新触发器和批更新后

  •  2
  • Jonas Stawski  · 技术社区  · 14 年前

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

    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
    

    因为我是从inserted和deleted中选择的,所以如果有人使用封装多行的where子句更新表,这是否有效?换句话说,插入和删除的表是否可以在我的触发器范围内包含多行?

    谢谢。。。

    2 回复  |  直到 14 年前
        1
  •  4
  •   KM.    14 年前

    为什么不使用instead of update触发器,只连接到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”不为空,则可以删除这两个 OR 中的条件 IF EXISTS

        2
  •  0
  •   Ashish    9 年前

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