如果只更新了2列,则触发T-SQL

时间:2017-03-24 22:31:41

标签: sql sql-server tsql

我正在尝试制作一个触发器,在更新表时记录2列(地址和邮政编码)的先前数据,包括更新的用户和时间戳。我还需要更新只有在两个列同时更新时才会发生,如果它们不是需要回滚的更改。我创建的表格:

CREATE TABLE PreviousAddress
    (
    a_user char (10)  ,
    a_date date ,
    a_ID int IDENTITY (1, 1) NOT NULL ,
    a_CustomerID int ,
    a_PrevAddr char (50),
    a_PrevPostCode char(10),
    CONSTRAINT [PK_Previous] PRIMARY KEY(a_id))

我找不到任何关于如何制作将数据插入此表的触发器的文档,但只有在邮政编码和地址都被编辑的情况下?

我的尝试:

CREATE TRIGGER Addr_Audit
    ON Customers
    AFTER UPDATE
    AS
    IF UPDATE(Cus_Addr) OR UPDATE(Cus_Post_Code)
    BEGIN
    INSERT INTO PreviousAddress
    SELECT CURRENT_USER, CURRENT_TIMESTAMP, CustomerID, CustomerAddress, CustomerPostcode FROM Deleted 
    END

1 个答案:

答案 0 :(得分:2)

不使用UPDATE,而是连接已删除和已插入的表,这将处理多个更新,并仅插入已更改的更新。

CREATE TRIGGER Addr_Audit
ON Customers
AFTER UPDATE
AS
    -- insert on PreviousAddres those records where
    -- both, Cus_Addr and Cus_Post_Code has changed
    --
    INSERT INTO PreviousAddress
    SELECT     d.CURRENT_USER, 
               d.CURRENT_TIMESTAMP, 
               d.CustomerID, 
               d.CustomerAddress, 
               d.CustomerPostcode 
    FROM       deleted d
    INNER JOIN inserted i
    ON         d.CustomerID = i.CustomerID
    WHERE      i.Cus_Addr <> d.Cus_Addr
    AND        i.Cus_Post_Code <> d.Cus_Post_Code

    -- Rollback changes on the other records.
    --
    UPDATE     Customers
    SET        Cus_Addr = d.Cus_Addr,
               Cus_Post_Code = d.Cus_Post_Code,
               --
               -- add other fields to rollback changes
               --
    FROM       Customers c
    INNER JOIN inserted i
    ON         i.CustomerID = c.CustomerID
    INNER JOIN deleted d
    ON         d.CustomerID = c.CustomerID
    WHERE      i.Cus_Addr = d.Cus_Addr
    OR         i.Cus_Post_Code = d.Cus_Post_Code

为了问题,我将添加另一个解决方案。如果检测到至少一个记录,其中只有一个字段Cus_Addr或Cus_Post_Code已更改,则此回滚全部更改。

CREATE TRIGGER Addr_Audit
ON Customers
AFTER UPDATE
AS
    -- check Cust_Addr and Cust_Post_Code, both has been changed
    -- if not, rollback the whole transaction and raises one error
    --
    IF EXISTS (SELECT     1
               FROM       inserted i
               INNER JOIN deleted d
               ON         i.CustomerID = d.CustomerID
               WHERE      (i.Cus_Addr <> d.Cus_Addr
                          AND 
                          (i.Cus_Post_Code = d.Cus_Post_Code)
               OR         (i.Cus_Addr = d.Cus_Addr
                          AND 
                          (i.Cus_Post_Code <> d.Cus_Post_Code)
               )
     BEGIN
         ROLLBACK TRANS;
         RAISERROR('ERROR: Must change P.C. and address',16,1);
     END


    -- insert on PreviousAddres those records where
    -- both, Cus_Addr and Cus_Post_Code has changed
    --
    INSERT INTO PreviousAddress
    SELECT     d.CURRENT_USER, 
               d.CURRENT_TIMESTAMP, 
               d.CustomerID, 
               d.CustomerAddress, 
               d.CustomerPostcode 
    FROM       deleted d
    INNER JOIN inserted i
    ON         d.CustomerID = i.CustomerID
    WHERE      i.Cus_Addr <> d.Cus_Addr
    AND        i.Cus_Post_Code <> d.Cus_Post_Code