我有一张Images
表,其中包含这些基本列 —
ImageId (int)
VotesUp (int)
VotesDown (int)
每张图片都可以获得赞成票(赞成票、反对票、撤回票)
upvotes 表有:
ImageId (int)
UserId (int)
Score (int ) [-1,0,+1]
因此,如果 -
然后用户插入 +1 分数(如果不存在)我向
upvotes
表中添加一个新行并更新表中的值Images
(以便快速获取)用户将其分数从 +1 更改为 0 然后降低
votes up
- 用户将其分数从 +1 更改为 -1,然后减少
votes up
和增加votes down
- 用户将其分数从 0 更改为 +1,然后增加
votes up
用户将其分数从 0 更改为 -1,然后增加
votes down
用户将其分数从 -1 更改为 0 然后减少
votes down
- 用户将其分数从 -1 更改为 +1,然后减少
votes down
和增加votes up
这是一个非常简单的逻辑。
这是upvotes
桌子上的触发器:
alter TRIGGER [dbo].[UpvotesChanged]
ON [dbo].[Upvotes]
FOR INSERT, UPDATE
AS
BEGIN
IF EXISTS( SELECT 1 FROM DELETED ) --update
BEGIN
UPDATE imgs
SET VotesUp = CASE
WHEN deleted.Score = 1 AND INSERTED.score =0 THEN ISNULL(VotesUp, 0) -1
WHEN deleted.Score = 1 AND INSERTED.score =-1 THEN ISNULL(VotesUp, 0) -1
WHEN deleted.Score = 0 AND INSERTED.score =1 THEN ISNULL(VotesUp, 0) +1
WHEN deleted.Score = -1 AND INSERTED.score =1 THEN ISNULL(VotesUp, 0) +1
ELSE ISNULL(VotesUp, 0)
END
,
VotesDown = CASE
WHEN deleted.Score = 0 AND INSERTED.score =-1 THEN ISNULL(VotesDown, 0) +1
WHEN deleted.Score = 1 AND INSERTED.score =-1 THEN ISNULL(VotesDown, 0) +1
WHEN deleted.Score = -1 AND INSERTED.score =1 THEN ISNULL(VotesDown, 0) -1
WHEN deleted.Score = -1 AND INSERTED.score =0 THEN ISNULL(VotesDown, 0) -1
ELSE ISNULL(VotesDown, 0)
END
FROM Images imgs
JOIN DELETED
ON imgs.ImageId = deleted.ImageId
JOIN INSERTED ON imgs.ImageId = INSERTED.ImageId
END
ELSE
--insert
BEGIN
UPDATE imgs
SET VotesUp = CASE
WHEN INSERTED.Score = 1
THEN ISNULL(VotesUp, 0) + 1
ELSE VotesUp
END,
VotesDown = CASE
WHEN INSERTED.Score = -1
THEN ISNULL(VotesDown, 0) + 1
ELSE VotesDown
END
FROM Images imgs
JOIN INSERTED
ON imgs.ImageId = INSERTED.ImageId
END
END
它按预期工作。
那么问题出在哪里呢?
问题 :
我认为这个触发器可以在没有所有这些 if's/cases 的情况下得到简化。我只是看不到简化。
是否可以简化此触发器?
我不使用触发器,而是使用索引视图。
这样,数据的两个视图将由 SQL Server 自动保持同步,而无需编写任何触发代码。您也不必担心微妙的竞争条件和其他潜在的并发问题。
索引视图
视图中的查询本质上是一个数据透视表。它不是使用
PIVOT
语法编写的,因为在 SQL Server 索引视图中不允许这样做。对于 Enterprise/Developer Edition,优化器将做出基于成本的决定是使用视图的索引,还是扩展视图并访问基表。您可以强制使用带
NOEXPAND
提示的视图索引。在其他版本中,您必须使用
NOEXPAND
提示来避免扩展视图。还有其他原因更喜欢NOEXPAND
对索引视图使用提示。例子