如何在ON INSTEAD OF UPDATE触发器

时间:2018-10-02 04:18:40

标签: sql-server tsql triggers

我正在尝试构造一个INSTEAD OF UPDATE触发器,以在执行插入操作之前修改要插入的列之一。如果表的PK在更新期间未更改,则工作正常。

如果表的PK已更新,我不知道如何编写更新语句来更新适当的行。我怎么知道要更新哪些行。

CREATE Table MyTest(ID int NOT NULL PRIMARY KEY,
                    Name NVARCHAR(40) NOT NULL);
GO

INSERT INTO MyTest VALUES(1,'Joe');
INSERT INTO MyTest VALUES(2,'Scott');
INSERT INTO MyTest VALUES(3,'Dan');
INSERT INTO MyTest VALUES(4,'Becky');

GO

CREATE TRIGGER Update_Please
ON MyTest
INSTEAD OF UPDATE
AS
BEGIN
    SET NOCOUNT ON

    IF EXISTS (SELECT id  
                 FROM INSERTED 
               EXCEPT 
               SELECT id
                 FROM DELETED)
        RAISERROR ('now what?',-1,-1);
        /* ======================================================
           oh heck! The PK in one or more rows was updated 
           in the update statement. How do I construct
           an update statement w/o joining to inserted on the PK?
           ====================================================== */

    ELSE
        BEGIN
            -- ALTER A COLUMN
            UPDATE M
               SET name = CASE WHEN I.NAME = 'Mike' THEN 'The Dude' ELSE  I.NAME END
              FROM MyTest M
              JOIN INSERTED I ON I.id = M.id;
        END
END

GO

UPDATE MyTest SET Name = 'Mike' WHERE id > 2; --works great!

UPDATE MyTest SET ID = 9 WHERE Name = 'Joe'; --how do I complete the update?

1 个答案:

答案 0 :(得分:2)

正如我在评论中所写,我认为您无法在instead of update触发器中完成此操作,但是使用for update做到这一点非常容易。原因是两个触发器之间的差异-在更新基础表之前,在{em> 之前触发了instead of update触发器,而在之后,触发了for update触发器。 >那个。这意味着inserted表中的任何值都与实际表中的值相同-因此只需将触发器从instead of update更改为for update

CREATE TRIGGER Update_Please
ON MyTest
FOR UPDATE
AS
BEGIN
    SET NOCOUNT ON
        UPDATE M
           SET name = CASE WHEN I.NAME = 'Mike' THEN 'The Dude' ELSE  I.NAME END
          FROM MyTest M
          JOIN INSERTED I ON I.id = M.id;

END

GO