2017-03-24 22 views
1

テーブルの更新時に、更新のユーザーとタイムスタンプを含む2列前のデータ(アドレスと郵便番号)を記録するトリガーを作成しようとしています。また、両方の列が同時に更新された場合にのみ更新が必要で、変更がロールバックされていない場合にのみ必要です。私が作成した表:2列しか更新されない場合のT-SQLトリガー

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

「OR」を「AND」に変更します。 –

+0

IF UPDATE(...)が機能している必要があります(あなたの場合はANDで使用します)。https://msdn.microsoft.com/de-de/library/ms187326.aspx – IngoB

答えて

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のいずれかのフィールドだけが変更されたレコードを少なくとも1つ検出すると、すべての変更をロールバックします。

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 
+0

質問から:「私も両方の列が同時に更新された場合にのみ更新が行われます。変更がロールバックされる必要がない場合:_「ロールバックはどうですか? (私は、列のうち1つだけではなく、両方の列が変更され、トランザクションをロールバックする行があることを意味しています)。別名:あなたはCustomerIdが一意であると仮定しました。多分、OPはその点を明確にすべきであろう。 – HABO

+0

@pukkaaあなたは 'Cus_Addr'と' Cus_Post_Code'の両方が変更されていない行だけに変更を元に戻すことを意味するために 'roll back 'を意図しましたか?' RaIsError'か 'RaIsError'でトランザクション全体の' rollback'何がうまくいったのかを示すために「スロー」する? – HABO

+0

@HABOこれは最良のオプションだと思います。ロールバックはトランザクション全体に影響します。しかし、私は2つのオプションを追加することができます。 – McNets

関連する問題