触发更新插入和删除的总记录

时间:2013-05-17 16:28:01

标签: sql-server triggers

我正在编写一个触发器,将一个表的记录计数存储为另一个表中的列,以加快大型数据库上的某些报告查询。

这是我到目前为止所做的,它在删除时工作正常,但我也需要在插入上工作。我需要使用单独的触发器吗?是否必须使用光标或是否有更有效的方法?

谢谢!

ALTER TRIGGER [dbo].[updateSourceTotals]
   ON  [dbo].imports
   AFTER INSERT, DELETE
AS 
BEGIN

    SET NOCOUNT ON;

    DECLARE @sourceId int;

    DECLARE deleteCursor CURSOR FOR SELECT DISTINCT sourceId FROM deleted

    OPEN deleteCursor

    FETCH NEXT FROM deleteCursor INTO @sourceId

    WHILE @@FETCH_STATUS = 0
    BEGIN

        UPDATE  sources
        SET     totalImports = (
                    SELECT  COUNT(*) 
                    FROM    imports 
                    WHERE   sourceId = @sourceId
                    )
        WHERE   id = @sourceId

    FETCH NEXT FROM deleteCursor INTO @sourceId
    END

    CLOSE deleteCursor
    DEALLOCATE deleteCursor 

END
GO

1 个答案:

答案 0 :(得分:2)

如果您确实设置了Trigger方法(并且 NOT 推荐它),那么这是当前代码的一个更简单且可能更快的版本:

ALTER TRIGGER [dbo].[updateSourceTotals]
   ON  [dbo].imports
   AFTER INSERT, DELETE
AS 
BEGIN

    UPDATE  s
    SET     totalImports = (
                SELECT  COUNT(*) 
                FROM    imports i
                WHERE   i.sourceId = s.Id
                )
    FROM    sources s
    WHERE   s.id IN(SELECT sourceId FROM deleted)

END

如果你想覆盖INSERT,也应该这样做:

ALTER TRIGGER [dbo].[updateSourceTotals]
   ON  [dbo].imports
   AFTER INSERT, DELETE
AS 
BEGIN

    UPDATE  s
    SET     totalImports = (
                SELECT  COUNT(*) 
                FROM    imports i
                WHERE   i.sourceId = s.id
                )
    FROM    sources s
    WHERE   s.id IN(
                    SELECT sourceId FROM deleted
                UNION
                    SELECT sourceId FROM inserted
                  )

END

作为额外的奖励,它也适用于UPDATE


为了澄清一下,即使在消除Cursor之后,在Trigger中进行预聚合的问题是,不是在每个请求上重新计算查询,而是在每个上重新计算它们。修改

即使在摘要中,如果你做了很多这样的请求,这只是一个胜利,但不要非常修改表。但是,在活动DBMS服务器的真实环境中,你甚至失去了大部分甚至这个小优势,因为如果你做了很多这样的请求,那么它们可能非常有效地被缓存(反过来,因为读取更多缓存 - 有效而不是写作。)