1

私は2つのテーブルを持っています。1 つのテーブルには、単にカウンターを保持するために使用される 1 つのフィールドがあり、もう 1 つのテーブルには多数の検索フィールドがあり、これらのフィールドの 1 つに他のテーブルのカウンター値が含まれている必要があります。

トリガーを作成しようとしています

  1. 2 番目のテーブルで更新が発生すると、最初のテーブルの値を 1 増やします
  2. 最初のテーブルから増分された値は、2 番目のテーブルのフィールドを設定するために使用されます
  3. 1 & 2 は、更新が 2 番目のテーブルで発生し、フィールド、つまりステータスが特定の値に等しい場合にのみ発生します。
  4. 複数のレコードに対して 1、2、および 3 を処理します。

1) なんとかこのトリガーを書きましたが、a) ひどく遅いようです。b) それをかなりよく説明している記事を見つけましたが、例が示すように、これは 1 つのレコードのみです。複数のレコードが更新された場合は解決策を提供しますが、私の問題は、各レコードの最初のテーブルの値をインクリメントしてから、個々のレコードをそれぞれの新しい値で更新する方法ですか?

なぜ遅いのか(まあ、SQL Server管理コンソールで)何か考えはありますか?

私が見つけた記事はhttp://benreichelt.net/blog/2005/12/13/make-a-trigger-fire-on-column-change/にあります。

この記事をもとに書いたトリガーは以下の通りです。

CREATE TRIGGER [dbo].[trig_DataTable] ON [dbo].[DataTable]
FOR UPDATE
AS
IF UPDATE(Status)
BEGIN
SET NOCOUNT ON;

  DECLARE @newStatus NVARCHAR(50)
  DECLARE @oldStatus NVARCHAR(50)   
  DECLARE @maxRefNo INT

  DECLARE @id BIGINT

  SET @maxRefNo = (SELECT MAX(RefNo) FROM CounterTable) + 1
  UPDATE CounterTable SET RefNo = @maxRefNo

  SET @newStatus = (SELECT Status FROM Inserted)
  SET @oldStatus = (SELECT Status FROM Deleted)

  IF (@newStatus != @oldStatus) AND (@newStatus = 'Approved')
  BEGIN   
    SET @Id = (SELECT Id FROM Inserted)
    UPDATE DataTable
    SET UniqueRef = @maxRefNo
    WHERE Id = @Id
  END

END

上記に関して、もう 1 つ質問があります。上記のトリガーは単一のレコードに対してのみ機能するため、where 部分が必要ですか? これを必要とするのは意味がないようです。

私が必要とするのは上記と同じ動作であるため、それほど重要ではありませんが、INSERTED/DELETED テーブルに含まれる複数のレコードに対してそれを処理する必要があります。

次の使用可能な番号を取得して CounterTable を更新する関数を作成し、記事で説明されているように、同様の SQL からこの関数を呼び出すことはできますか?

INSERT INTO PriceHistory(ItemId, OldPrice, NewPrice, UniqueRef)
 SELECT I.ItemId, D.Price, I.Price, dbo.GetNextRefNo()
 FROM INSERTED I INNER JOIN DELETED D ON I.ItemId = D.ItemId
 WHERE I.Price != D.Price

正直に言うと... すぐに試してみますが、これを達成する方法についてアイデアをお持ちの方がいらっしゃいましたら、お知らせください... 素晴らしいことです! ありがとう。

上記が理にかなっていることを願っています。

乾杯。

T.

4

1 に答える 1

3

以下のクエリを使用:

CREATE TRIGGER [dbo].[trig_DataTable] ON [dbo].[DataTable]
FOR UPDATE
AS BEGIN
    SET NOCOUNT ON;
    DECLARE @maxRefNo INT
    DECLARE @id BIGINT

    SET @maxRefNo = ISNULL((SELECT MAX(RefNo) FROM CounterTable),0)

    UPDATE CounterTable 
    SET RefNo = @maxRefNo + (SELECT COUNT(*) 
                            FROM INSERTED A 
                            INNER JOIN DELETED D ON D.id=A.id
                            WHERE A.STATE = 'Approved'
                              AND A.STATE <> D.State)

    UPDATE DataTable
    SET UniqueRef = @maxRefNo + ROW_NUMBER() OVER (ORDER BY A.id)
    FROM INSERTED A
    INNER JOIN DELETED D ON D.id = A.id
    WHERE DataTable.Id = A.Id
        AND A.STATE = 'Approved'
        AND A.STATE <> D.State
END

トリガーを作成するときは、挿入されたテーブルの複数のレコードでトリガーを実行する必要があります。誰も記録しない。

于 2012-08-28T04:20:49.793 に答える