0

すべてのビューを特定のページに記録するテーブル Views にトリガーがあります。このトリガーは、挿入されたフィールドによって導出される必要がある合計ビューで会社テーブルを更新します。実際には、1 つの会社が複数のビューを取得することはありません (すべてを選択して 1 つ追加するだけで十分です) が、私は安全にコーディングするのが好きなので...

企業: ID、ビュー

CompanyViews: Id、CompanyId

必要なトリガー:

UPDATE Companies 
    SET Views = Views + (SELECT Count(1) FROM INSERTED  AS i WHERE i.CompanyId = Id) 
    WHERE Id IN (SELECT DISTINCT(CompanyId) FROM INSERTED)

しかし、これは...うまくいきません。理由はよくわかりませんが、基本的に意図した結果は次のとおりです。

Id, CompanyId
1   2
2   2
3   3
4   5
5   2
6   3

この場合、会社 2 は 3 つのビューを取得し、会社 3 は 2 つのビューを取得し、会社 5 は 1 つのビューを取得します。

クエリが失敗した場合、どうすればよいですか?

編集:「機能しない」とは、値が変更されないことを意味します。実際、検出した行 (つまり、DISTINCT 値) の代わりに NULL を挿入します。Views + を省略すると、単純に 0 になります。

4

1 に答える 1

0

トリガーを使用してこのデータを手動で追跡し、同時実行の問題に対処する理由がわかりません。別のトリガーで削除の数を減らすようにしてください。代わりに、インデックス付きビューを作成し、SQL Server を許可します。あなたのために仕事をしてください:

CREATE VIEW dbo.CompanyViewTotals
WITH SCHEMABINDING
AS
  SELECT CompanyId, Views = COUNT_BIG(*)
    FROM dbo.CompanyViews
    GROUP BY CompanyId;
GO
CREATE UNIQUE CLUSTERED INDEX x ON dbo.CompanyViewTotals(CompanyId);
GO

はい、これはインサートに負担がかかりますが、トリガーにも負担がかかります。これには、常に正しいという追加の利点があり、トリガーを削除でき、テーブルの無駄なViews列を削除できますCompanies。インデックス付きビューがなくても、これは明らかに冗長なデータであり、その列がなくても取得できます。

Entity Framework でこれらのくだらない制限をすべて回避できない場合は、トリガーを使用して、遅くて信頼性の低い方法で回避できます。insertedとベース テーブルとの間の適切な相関関係を使用し、ベース テーブルの潜在的な値を適切に考慮するように、更新ステートメントを修正する必要がありNULLます。

;WITH cte(CompanyId,NewViews) AS 
(
  SELECT CompanyId, COUNT(CompanyId) 
    FROM inserted 
    GROUP BY CompanyId
)
UPDATE c
  SET c.Views = COALESCE(c.Views, 0) + cte.NewViews
  FROM cte INNER JOIN dbo.Companies AS c
  ON cte.CompanyId = c.CompanyId;
于 2013-04-17T17:37:48.730 に答える