4

これは、データベース行への変更を簡単に追跡するための最良の方法ですか。

ALTER TRIGGER [dbo].[trg_121s] 
ON  [dbo].[121s]
  AFTER UPDATE
AS 
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;

-- Insert statements for trigger here

update dbo.[121s]
set modified=getdate()
where id in 
(select distinct ID from Inserted)

END

したがって、[121s]の行を更新すると、変更された列が更新されます。

それは機能しますが、これを達成するための最良の方法かどうかはわかりません。

私はこの行で少し混乱しています:

(select distinct ID from Inserted)

...そして、正しい行IDを取得していることをどのように知るか。

確認/説明をありがとう、

マーク

4

3 に答える 3

25

insertedは疑似テーブルであり、UPDATEステートメントの影響を受けたすべての正しい行が確実に含まれています(主キーの場合、テーブルがどのような名前であるかを判断するのは難しいですが、DISTINCT必要ないと思います)。それらすべてが実際に値を変更したかどうかは、変更された日付/時刻を適用する前に検証することを検討できるもう1つのことです。それを除けば、私はおそらくこのようにするでしょう:ID121s

ALTER TRIGGER [dbo].[trg_121s] 
ON [dbo].[121s]
AFTER UPDATE
AS 
BEGIN
  SET NOCOUNT ON;

  UPDATE t SET modified = CURRENT_TIMESTAMP
   FROM dbo.[121s] AS t
   WHERE EXISTS (SELECT 1 FROM inserted WHERE ID = t.ID);
   -- WHERE EXISTS is same as INNER JOIN inserted AS i ON t.ID = i.ID;
END
GO

すべてが同じタイムスタンプで更新されることを100%確実に保証したい場合(このユースケースで複数の値を見たことがあるかどうかはわかりませんが):

ALTER TRIGGER [dbo].[trg_121s] 
ON [dbo].[121s]
AFTER UPDATE
AS 
BEGIN
  SET NOCOUNT ON;

  DECLARE @ts DATETIME;
  SET @ts = CURRENT_TIMESTAMP;

  UPDATE t SET modified = @ts
   FROM dbo.[121s] AS t
  INNER JOIN inserted AS i 
  ON t.ID = i.ID;
END
GO

また、たとえば列のfoo値が変更された場合にのみ更新が行われるようにする場合は、次のように言うことができます。

  UPDATE t SET modified = @ts
   FROM dbo.[121s] AS t
   INNER JOIN inserted AS i
   ON t.ID = i.ID
   AND t.foo <> i.foo;

fooこれは一般的なパターンですが、null許容の場合は、SQL Serverが一方の側に値があり、もう一方の側に値がない(または両方がない)行で一致できないため、より複雑になります。その場合、これを行います。

   AND 
   (
     t.foo <> i.foo
     OR (t.foo IS NULL AND i.foo IS NOT NULL)
     OR (t.foo IS NOT NULL AND i.foo IS NULL)
   );

一部の人々は、次のように「魔法の値に対してCOALESCEまたはISNULLを使用できます」と言うでしょう。

WHERE COALESCE(t.foo, 'magic') <> COALESCE(i.foo, 'magic')

...そして、これに対して警告します。データに存在できない魔法の値を常に検索しているからです。

于 2012-09-17T15:25:57.683 に答える
2

挿入されるのは、トリガーを起動した操作(挿入/更新)の影響を受ける行を含むテーブルです。したがって、ここでのトリガーは正しいです。Idが主キーの場合、distinctは必要ありません(Insertedからidを選択するだけで十分です)。Idが主キーでない場合、トリガーはfalseになります。これは、必要以上に更新する可能性があるためです。

于 2012-09-17T15:22:41.367 に答える
1

Stackoverflowだけでなく、世界中の多くの人がトリガーは悪だと言うでしょうが、悪用されていないときは価値があると言えます。ここで、このトリガーを使用したい場合、それは有効であるように見え、Insertedテーブルには、このトリガーを起動したステートメントによって更新された行が含まれています。これは正しいですが、が主キーのDISTINCT場合はおそらく削除できます。ID

ただし、柔軟性がある場合の別のオプションは、timestamp代わりに列を使用することです。ただし、混同しないでください。timestamp列は日付と時刻に相関していません。したがって、日付と時刻が必要な場合は、そこにあるものに固執してください。

于 2012-09-17T15:24:08.387 に答える