我最近创建了一个SQL触发器来替换我以前运行的非常昂贵的查询,以减少我的数据库每天所做的更新量。
在我进行更新之前,我会检查当天已经发生了多少次更新,这通常是通过查询来完成的:
SELECT COUNT(*) FROM Movies WHERE DateAdded = Date.Now
我的数据库有超过100万条记录,这个查询每分钟运行1-2k左右,所以你可以看到我为什么要为此采用新的方法。
因此,当在Movie表上发生任何INSERT或UPDATE时,我创建了一个审计表并设置了一个SQL触发器来更新此表。但是我注意到审计表每天都不同步几百(审计表计数高于电影表中的实际更新)。由于这不会造成很大的问题,我只是好奇可能导致这种情况或如何进行调试?
SQL触发器:
ALTER TRIGGER [dbo].[trg_Audit]
ON [dbo].[Movies]
AFTER UPDATE, INSERT
AS
BEGIN
UPDATE Audit SET [count] = [count] + 1 WHERE [date] = CONVERT (date, GETDATE())
IF @@ROWCOUNT=0
INSERT INTO audit ([date], [count]) VALUES (GETDATE(), 1)
END
上述触发器仅在Movie表上的UPDATE或INSERT之后发生,并尝试更新Audit表中的count + 1,如果它不存在(IF @@ ROWCOUNT = 0),则它会创建它。任何帮助将非常感激!感谢。
答案 0 :(得分:2)
这样的事情应该有效:
create table dbo.Movies (
A int not null,
B int not null,
DateAdded datetime not null
)
go
create view dbo.audit
with schemabinding
as
select CONVERT(date,DateAdded) as dt,COUNT_BIG(*) as cnt
from dbo.Movies
group by CONVERT(date,DateAdded)
go
create unique clustered index IX_MovieCounts on dbo.audit (dt)
这称为indexed view。优点是SQL Server负责维护存储在此视图中的数据,而且它始终是正确的。
除非您使用的是Enterprise / Developer版,否则您需要使用audit
提示查询NOEXPAND
视图:
SELECT * from audit with (noexpand)
这有以下优点
a)您现在不必自己编写触发器(SQL Server确实有一些与幕后触发器非常相似的东西),
b)它现在可以处理多行插入,更新和删除,以及
c)您不必编写逻辑来应对更改DateAdded
值的更新。
答案 1 :(得分:1)
不是将计数递增1,而应该将它增加一个已经改变的记录数。例如
UPDATE Audit
SET [count] = [count] + (SELECT COUNT(*) FROM INSERTED)
WHERE [date] = CONVERT (date, GETDATE())
IF @@ROWCOUNT=0
INSERT INTO audit ([date], [count])
VALUES (GETDATE(), (SELECT COUNT(*) FROM INSERTED))