現在、トリガーは常に1行の挿入があることを前提としています。このようなものでトリガーを試しましたか?
INSERT dbo.[poll-options](option_order --, ...)
VALUES(1 --, ...),
(2 --, ...);
また、SQL Serverは「挿入されたテーブルにアクセスできない」と言いますが、ステートメントはこれを示しています。どこを参照しますかinserted
(これが有効なサブクエリ構造であったとしても)?
SET @count = (SELECT COUNT (*) FROM [poll-count]
WHERE option_order = i.option_order)
-----------------------^ "i" <> "inserted"
inserted
これは、複数行の挿入を適切に参照し、適切に処理するトリガーです。
CREATE TRIGGER dbo.pollupdate
ON dbo.[poll-options]
FOR INSERT
AS
BEGIN
SET NOCOUNT ON;
;WITH x AS
(
SELECT option_order, c = COUNT(*)
FROM dbo.[poll-options] AS p
WHERE EXISTS
(
SELECT 1 FROM inserted
WHERE option_order = p.option_order
)
GROUP BY option_order
)
UPDATE p SET total = x.c
FROM dbo.[poll-options] AS p
INNER JOIN x
ON p.option_order = x.option_order;
END
GO
しかし、なぜこのデータをすべての行に保存したいのですか?実行時にいつでもカウントを導き出し、それが完全に最新であることを認識し、トリガーの必要性を完全に回避することができます。実行時にカウントを導出するパフォーマンスの側面に関する場合、DML中にほぼ同じメンテナンスコストでこの先行書き込み最適化を実装するはるかに簡単な方法は、インデックス付きビューを作成することです。
CREATE VIEW dbo.[poll-options-count]
WITH SCHEMABINDING
AS
SELECT option_order, c = COUNT_BIG(*)
FROM dbo.[poll-options]
GROUP BY option_order;
GO
CREATE UNIQUE CLUSTERED INDEX oo ON dbo.[poll-options-count](option_order);
GO
これでインデックスが維持され、任意の(またはすべての)option_order
値の非常に迅速なカウントを導き出すことができます。もちろん、クエリ時間の改善がメンテナンスを増やす価値があるかどうかをテストします(ただし、特定の挿入でさらに多くの行に影響を与える可能性があることを除いて、トリガーでその価格をすでに支払っています...) 。
-
最後の提案として、オブジェクト名のように特殊文字を使用しないでください。それはあなたに常にそれを包むことを強制するだけで[square brackets]
あり、それは誰にとっても楽しいことではありません。