我的表格上有一个触发器,用于记录特定页面的所有视图。此触发器使用总视图更新公司表,该视图应由插入的字段派生。在实际情况下,一个公司不应该获得多个视图(所以只选择所有视图并添加一个就足够了),但我喜欢安全编码,所以...
公司: 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。
答案 0 :(得分: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;