処理の一部を最適化しようとしています。同期したいステータスを持つ 2 つのテーブル (ジョブとバケット) があります。つまり、誰かがジョブのステータスを変更した場合、バケットのステータスを変更することもあれば、バケットのステータスを変更するときに、添付されたジョブのステータスを変更したい場合もあります。この点で、主に「キャンセル」を意味する場合がありますが、ジョブからバケットへの完了/エラーも意味します。
それらに 2 つの状態がある理由は、(a) それらは独立したサブシステムであり、たとえばジョブを一時停止することが可能であり、(b) すべてのジョブがバケットに接続されているわけではない ;)
ジョブの更新時とバケットの更新時の2つのトリガーでそれを試してみましたが、ジョブのトリガーがバケットを変更するたびに、バケットのトリガーがトリガーされるようです。おもしろいことに、これは更新後のトリガーですが、トリガーは他のテーブルの変更を認識していないようです....これは再帰につながります。
トリガーは次のとおりです。
ALTER TRIGGER [grd].[Job_UpdateBucket]
ON [grd].[Job]
AFTER UPDATE
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
UPDATE
[simstg].[Bucket]
SET
[Status] = i.[Status],
[StatusTimestamp] = GETUTCDATE()
FROM
[simstg].[Bucket] b
JOIN [inserted] i ON (b.[JobRef] = i.[Id])
WHERE
i.[Status] IN ('C', 'F', 'X', 'A')
AND b.[Status] <> i.[Status]
AND b.[Status] NOT IN ('X')
END
と
ALTER TRIGGER [simstg].[Bucket_UpdateJob]
ON [simstg].[Bucket]
AFTER UPDATE
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
UPDATE
[grd].[Job]
SET
[Status] = 'X',
[LastUpdate] = GETUTCDATE()
FROM
[grd].[Job] j
JOIN [inserted] i ON (j.Id = i.JobRef)
WHERE
i.[Status] = 'X'
AND j.[Status] <> i.[Status]
END
これは、私は長い間 SQL をやっていますが、この型または再帰を持つのは初めてです。where条件はAFTERトリガーであるため、再帰を回避すると考えました。ジョブがバケットを更新すると、バケットトリガーはジョブで既に変更されたステータスを確認する必要があるため、再帰はありません。
これにより、次の 2 つの疑問が生じます。
1: 私は間違っていますか? ジョブを更新すると、トリガーはバケットを変更し、バケットのトリガーはジョブで変更されたデータを確認する必要がありますか? これにより、ステータスが新しいステータスと異なることを比較する WHERE 条件により、再帰を回避できるはずです。
2: ここで再帰を避ける他の方法はありますか?