2012-08-27 52 views
70

他の例を見てみましょうが、私が望むようには機能していないようです:QtyToRepairの値更新されました...しかし、それはしません。カラムが変更された場合にのみSQLの更新トリガー

私がどこをコメントアウトすれば、すべての場合に変更された情報が更新されます。私が他の例を挙げると、私は楽観的になりました。どんな手がかりもありがとう。ありがとう。

ウォルター

ALTER TRIGGER [dbo].[tr_SCHEDULE_Modified] 
    ON [dbo].[SCHEDULE] 
    AFTER UPDATE 
AS 
BEGIN 
    SET NOCOUNT ON; 

    UPDATE SCHEDULE SET modified = GETDATE() 
     , ModifiedUser = SUSER_NAME() 
     , ModifiedHost = HOST_NAME() 
    FROM SCHEDULE S 
    INNER JOIN Inserted I on S.OrderNo = I.OrderNo and S.PartNumber = I.PartNumber 
    WHERE S.QtyToRepair <> I.QtyToRepair 
END 
+1

あなたはどのようなDBを使用していますか? –

+1

loooks like SQL server –

+7

'update()'に関する警告 - 更新リストに列が現れているかどうかだけを検査し、挿入の場合は常に真です。行の値が変更されているかどうかはチェックされません。値が変更されている行と変更されていない行が複数ある可能性があるからです。 –

答えて

93

あなたの質問には2つの方法があります:あなたのトリガーに

の1-使用更新コマンドを。あなたがテーブルSCHEDULEと新しい値に設定QtyToRepair列の更新コマンドを使用すると、古い値と新しい値が等しい場合

ALTER TRIGGER [dbo].[tr_SCHEDULE_Modified] 
    ON [dbo].[SCHEDULE] 
    AFTER UPDATE 
AS BEGIN 
    SET NOCOUNT ON; 
    IF UPDATE (QtyToRepair) 
    BEGIN 
     UPDATE SCHEDULE 
     SET modified = GETDATE() 
      , ModifiedUser = SUSER_NAME() 
      , ModifiedHost = HOST_NAME() 
     FROM SCHEDULE S INNER JOIN Inserted I 
     ON S.OrderNo = I.OrderNo and S.PartNumber = I.PartNumber 
     WHERE S.QtyToRepair <> I.QtyToRepair 
    END 
END 

2 - 使用は1で、挿入されたテーブルと削除されたテーブル

ALTER TRIGGER [dbo].[tr_SCHEDULE_Modified] 
    ON [dbo].[SCHEDULE] 
    AFTER UPDATE 
AS BEGIN 
    SET NOCOUNT ON;  

    UPDATE SCHEDULE 
    SET modified = GETDATE() 
     , ModifiedUser = SUSER_NAME() 
     , ModifiedHost = HOST_NAME() 
    FROM SCHEDULE S 
    INNER JOIN Inserted I ON S.OrderNo = I.OrderNo and S.PartNumber = I.PartNumber 
    INNER JOIN Deleted D ON S.OrderNo = D.OrderNo and S.PartNumber = D.PartNumber     
    WHERE S.QtyToRepair <> I.QtyToRepair 
    AND D.QtyToRepair <> I.QtyToRepair 
END 

の間に参加または複数行、ソリューション1はスケジュールテーブルの更新された行をすべて更新しますが、ソリューション2の更新は古い値が新しい値と等しくない行のみをスケジュールします。

+0

申し訳ありませんが、それがSQLServerだと言及していません。私は削除されたテーブルを使用する必要がありました。私は別のテーブルに書き留めてしまった(歴史を維持するために)。 –

+5

カラムが同じ値に変更されている場合にトリガを起動させたくない場合は、アプローチ2が良いです。 – Neolisk

+0

私は何かが不足していると思うかもしれませんが、アプローチ#1はうまくいかないでしょう。なぜなら、これは*更新後ですから、現在の行は常に挿入行と同じ値を持つからです。 – Rob

5

あなたは、次の操作を実行したい:

ALTER TRIGGER [dbo].[tr_SCHEDULE_Modified] 
    ON [dbo].[SCHEDULE] 
    AFTER UPDATE 
AS 
BEGIN 
SET NOCOUNT ON; 

    IF (UPDATE(QtyToRepair)) 
    BEGIN 
     UPDATE SCHEDULE SET modified = GETDATE() 
      , ModifiedUser = SUSER_NAME() 
      , ModifiedHost = HOST_NAME() 
     FROM SCHEDULE S 
     INNER JOIN Inserted I ON S.OrderNo = I.OrderNo AND S.PartNumber = I.PartNumber 
     WHERE S.QtyToRepair <> I.QtyToRepair 
    END 
END 

このトリガーは値が同じであるかどうか、あなたが列に関係なく更新するたびに発生しますのでご注意ください。

11

最初にQtyToRepairが更新されているかどうかを確認する必要があります。

ALTER TRIGGER [dbo].[tr_SCHEDULE_Modified] 
    ON [dbo].[SCHEDULE] 
    AFTER UPDATE 
AS 
BEGIN 
SET NOCOUNT ON; 
    IF UPDATE (QtyToRepair) 
    BEGIN 
     UPDATE SCHEDULE 
     SET modified = GETDATE() 
      , ModifiedUser = SUSER_NAME() 
      , ModifiedHost = HOST_NAME() 
     FROM SCHEDULE S INNER JOIN Inserted I 
      ON S.OrderNo = I.OrderNo and S.PartNumber = I.PartNumber 
     WHERE S.QtyToRepair <> I.QtyToRepair 
    END 
END 
10

私がなってしまったFYIコード:

IF UPDATE (QtyToRepair) 
    begin 
     INSERT INTO tmpQtyToRepairChanges (OrderNo, PartNumber, ModifiedDate, ModifiedUser, ModifiedHost, QtyToRepairOld, QtyToRepairNew) 
     SELECT S.OrderNo, S.PartNumber, GETDATE(), SUSER_NAME(), HOST_NAME(), D.QtyToRepair, I.QtyToRepair FROM SCHEDULE S 
     INNER JOIN Inserted I ON S.OrderNo = I.OrderNo and S.PartNumber = I.PartNumber 
     INNER JOIN Deleted D ON S.OrderNo = D.OrderNo and S.PartNumber = D.PartNumber 
     WHERE I.QtyToRepair <> D.QtyToRepair 
end 
+1

これは役に立ちました。最初の基準が発動/照合されることは決してありませんでした。挿入されたテーブルは常に実際のテーブル値と一致しました。 WHERE I.QtyToRepair <> D.QtyToRepairを使用して私の鍵となりました。また、 'IF UPDATE(field)'は、複数のトリガが起動するのを助けます。 – Firegarden

関連する問題