Microsoft sql触发器更新多行

时间:2016-11-25 19:14:27

标签: sql-server tsql triggers

我有两个表,一个是Customers和一个Sales表。 我正在尝试创建一个触发器,以便在更新Sales表时更新customer表中的销售量。

CREATE TRIGGER salesUPDATE
ON SALES
AFTER INSERT
AS
UPDATE Customers
SET salesAmount = Sales.Amount
GO

但我得知销售不存在。我应该使用加入吗? 这会触发更新所有列,还是需要指定要更新的列?

3 个答案:

答案 0 :(得分:1)

CREATE TRIGGER salesUpdate ON SALES
AFTER INSERT, UPDATE, DELETE
AS
BEGIN

    ;WITH cteAffectedCustomers AS (
       SELECT DISTINCT CustomerId
       FROM
          inserted

       UNION 

       SELECT DISTINCT CustomerId
       FROM
          deleted
    )

    , cteAggregations AS (
       SELECT
          ca.CustomerId
          ,SUM(ISNULL(s.Amount,0)) as SalesAmount
          ,COUNT(s.SalesId) as NumOfSales
       FROM
          cteAffectedCustomers ca
          INNER JOIN Customers c
          ON ca.CustomerId = c.CustomerId
          LEFT JOIN Sales s
          ON ca.CustomerId = s.CustomerId
       GROUP BY
          ca.CustomerId
    )

    UPDATE c
       SET SalesAmount = ca.SalesAmount
          ,NumOfSales = ca.NumOfSales
    FROM
       Customers c
       INNER JOIN cteAggregations ca
       ON c.CustomerId = ca.CustomerId

END

以下是为维护预先聚合的值而需要创建的逻辑类型的示例。如果您想在SUM表中Amount Sales,则需要AFTER INSERT, UPDATE, and DELETE。然后你需要:

  • 确定所有受影响的客户因此您不会更新整个客户表
  • 进行汇总
  • 使用内部联接更新为聚合数据

关于触发器的注释,它们是基于集合的操作而不是标量。这意味着它们为x#行触发一次,而不是x#行的x次。因此,您必须在更新期间考虑多个记录,并且在将一个表与另一个表更新时,就像在触发器外部一样进行连接。

这会对写入操作产生性能影响但会加快读取速度,但是如果您没有处理极高读取操作量,则最好使用视图/查询并优化索引。聚合数据同步的可能性越来越小。如果你确实采用了触发路径,我建议你在一些合理的增量(夜间)上设置一个SQL作业,检查并纠正可能发生的任何不一致。

答案 1 :(得分:0)

使用魔术表插入

CREATE TRIGGER salesUPDATE
ON SALES
AFTER INSERT
AS
BEGIN
  Declare @Amount varchar(50) = (Select top 1 Amount from inserted)
  UPDATE Customers
  SET salesAmount = @Amount
END
GO

注意:前1位用于插入多条记录

答案 2 :(得分:-1)

使用包含新值的inserted表名:

CREATE TRIGGER salesUPDATE
ON SALES
AFTER INSERT
AS
UPDATE Customers
SET salesAmount = inserted.Amount
GO