他のテーブルに新しい行があるときに1つのテーブルを更新する必要があるトリガーに問題があります。
私は2つのテーブルを持っています:
最初:
SELECT
[Id], [Timestamp], [MachineName], [StatusId], [Quantity]
FROM [dbo].[Events]
そして2番目のもの:
SELECT
[Id], [MachineName], [StatusId], [QuantitySum], [StatusLastRefresh]
FROM [dbo].[ActualParams]
テーブルに[Events]
は、StreamAnalyticsからのすべてのマシンのすべてのステータス変更が表示されます。新しい行ごとに、2番目のテーブルが更新され、すべてのマシンの最後の値が表示され、最後のタイムスタンプがStatusLastRefreshに表示されます。実際、テーブルに[ActualParams]
は4行のデータがあります。
私はそうするために2つのトリガーを試しました:
ALTER TRIGGER [dbo].[AfterInsertEvent]
ON [dbo].[Events]
AFTER INSERT
AS
MERGE ActualParams AS ap
USING (SELECT Id, Machine, Status, Timestamp, Quantity
FROM inserted) AS ev ON ev.MachineName = ap.MachineName
WHEN MATCHED THEN
UPDATE SET map.StatusId = ev.StatusId,
ap.StatusLastRefresh = ev.Timestamp,
ap.QuantitySum = ap.QuantitySum + ev.Quantity;
トリガー#2:
ALTER TRIGGER [dbo].[AfterInsertEvent]
ON [dbo].[Events]
AFTER INSERT
BEGIN
DECLARE @mn nchar(10), @si int, @ts datetime2(7), @q int
SELECT @mn = MachineName, @si = StatusId, @ts = Timestamp, @q = Quantity
FROM inserted
UPDATE ActualParams
SET StatusId = @si,
StatusLastRefresh = @ts,
QuantitySum = QuantitySum + @q
WHERE ActualParams.MachineName = @mn
END
しかし、それらのどれも100%正しく機能しません。
まず、Merge
挿入された行がMachineName
同時に1つずつある場合、トリガーは正常に機能しますが、同じMachineName
挿入に対して同時に新しい行がほとんどない場合があり、同時に多くの行を1つに書き込むことができないというエラーが発生します。すべてが行き詰まります。
次に、単純なUpdate
トリガーは行をスキップすることがあり、ActualParamsテーブルには実際ではなく以前のStatusId値があります。実際、私は4台のマシンを持っていますが、通常、そのうちの1台のStatusIdが間違っています。20台以上になるとどうなるのかしら。
MachineName
すべてのマシンに固有です。
UPDATEでCURSORを試しましたが、それでも行がスキップされ、ステータスが実際ではない場合があります。
CURSORとMERGEを組み合わせる方法がわかりません。おそらくそれが解決策になるでしょう。
2番目のテーブルにも数量を要約したいので、すべての行で反応する必要があります。そのため、どの行もスキップできません(以前に忘れてしまった-編集済み)
何か案は?SSMS17を使用しています。
これをupdate
/で書いてみませんjoin
か?
UPDATE ap
SET StatusId = i.StatusId,
StatusLastRefresh = i.TimeStamp
FROM ActualParams ap
inserted i
ON ap.MachineName = i.MachineName;
同じマシンを1回で複数回更新できる場合は、insert
ウィンドウ関数を使用して最後の行を取得します。
UPDATE ap
SET StatusId = i.StatusId,
StatusLastRefresh = i.TimeStamp
FROM ActualParams ap
(SELECT i.*,
ROW_NUMBER() OVER (PARTITION BY MachineName ORDER BY TimeStamp DESC) as seqnum
FROM inserted i
) i
ON ap.MachineName = i.MachineName AND seqnum = 1;
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加