0

我的表视图上有一个触发器,它将所有视图记录到特定页面。此触发器使用应由插入字段派生的总视图更新公司表。在实际情况下,永远不会发生一家公司获得多个视图(因此只需选择所有视图并添加一个就足够了),但我喜欢安全地编码,所以...

公司: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 次观看。

当我的查询失败时,我应该如何处理?

编辑:通过“不起作用”,我的意思是,值保持不变。事实上,它会将 NULL 插入它确实检测到的行(即 DISTINCT 值)。如果我省略了 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 回答