2016-11-25 3 views
1

У меня есть две таблицы - таблица Customers и Sales. Я пытаюсь создать триггер для обновления объема продаж в таблице клиентов при обновлении таблицы продаж.Microsoft 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' будет добавлено более одной строки за раз. (ну, в зависимости от СУБД) – 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 значения. Если вы хотите SUM a Amount в таблице Sales, вам понадобится AFTER INSERT, UPDATE, and DELETE. Тогда вам нужно будет:

  • определить все пострадавшие клиент Таким образом, вы не обновлять всю таблицу клиентов
  • сделать агрегацию
  • обновления с внутренним присоединиться к агрегированным данным

Замечание о триггерах, это операция, основанная на наборе, не являющаяся скаляром. Это означает, что они стреляют один раз для x # строк NOT 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 для вставки нескольких записей

Смежные вопросы