2016-11-25 114 views
1

我有兩個表,一個Customers和一個Sales表。 我正試圖創建一個觸發器來更新銷售表時更新客戶表中的銷售額。微軟sql觸發器更新多行

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

但我得知銷售不存在。我應該使用連接嗎? 此觸發器是否會更新所有列,還是需要指定要更新哪一列?

+0

是的,是的,是的插入。 – RBarryYoung

+1

@RBarryYoung我認爲是的,不,是的,是的 –

+0

另外,作爲一般規則,您不希望在SQL數據庫中進行這種預聚合。相反,您應該創建查詢和/或視圖,以「按需」方式進行彙總。 – RBarryYoung

回答

-1

使用含有新值inserted表名:

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

注意:如果一次將多個行插入'Sales'中,將無法正常工作。 (好吧,取決於DBMS) – RBarryYoung

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 

這是邏輯的,你需要創建,以保持預agregated值類型的實例。如果要在Sales表中輸入SUMAmount,則需要輸入AFTER INSERT, UPDATE, and DELETE。然後,你將需要:

  • 確定所有受影響的客戶,所以你不更新整個客戶表
  • 做聚合
  • 更新一個內連接來彙總數據

關於觸發器的說明,它們是基於集合的操作而非標量。這意味着它們會針對x行的每行觸發一次,而針對x行的每行只觸發一次。因此,在更新過程中必須考慮多個記錄,並且在更新一個表時使用另一個表時會像觸發器之外那樣進行連接。

這對性能的影響寫操作但並加快你的閱讀,但是如果你不是在一個非常非常高的讀取量的操作,你會做的更好使用視圖/查詢和優化索引。聚合數據同步的可能性很小。如果你確實走了觸發路線,我建議你也有一個合理的增量(夜間)SQL工作,檢查和糾正可能發生的任何不一致。

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的多個記錄