Почему триггер делает ненужное вычитание после запроса в sql?

У меня есть две таблицы:

  1. Заказ и
  2. Продукт.

Я хочу, чтобы определенный столбец (OnShelfQuantity) в таблице Product обновлялся по мере добавления новой строки в таблицу Order. Я использовал приведенный ниже запрос для реализации триггера, который это сделает. Но проблема в том, что когда я вставляю строку в таблицу «Заказ», а затем проверяю таблицу «Продукт», чтобы увидеть изменения, я замечаю, что таблица «Продукт» обновлялась 3 раза. Например: Вставленное количество заказа = 10, тогда только 10 следует вычесть из Product_TAB.OnShelfQuantity. Но 30 вычитается. Пожалуйста помоги!

create trigger dbo.Trigge
ON dbo.Ordertable
AFTER INSERT 
AS
BEGIN
update Product_TAB set OnShelfQuantity= Product_TAB.OnShelfQuantity - Ordertable.Quantity
FROM dbo.Product_TAB
  INNER JOIN Ordertable
  ON Ordertable.ProductID = Product_TAB.ProductID;
END;

person Muhammad Salman Ali    schedule 11.01.2021    source источник
comment
Какие СУБД вы используете? (Этот код зависит от продукта.)   -  person jarlh    schedule 11.01.2021
comment
@jarth Это SQL-сервер, и я использую SSMS для реализации кода.   -  person Muhammad Salman Ali    schedule 11.01.2021
comment
Таблица Product была обновлена ​​3 раза ... так есть ли в таблице Ordertable три строки для данного ProductID? Вы, вероятно, захотите прочитать inserted и deleted виртуальные таблицы, используемые в триггерах.   -  person AlwaysLearning    schedule 11.01.2021
comment
Этот триггер, вероятно, лучше всего реализован с индексированным представлением.   -  person Charlieface    schedule 11.01.2021
comment
@AlwaysLearning Большое спасибо!   -  person Muhammad Salman Ali    schedule 11.01.2021
comment
@Charlieface Большое спасибо!   -  person Muhammad Salman Ali    schedule 11.01.2021
comment
Хотите реализовать свой вопрос?   -  person Charlieface    schedule 11.01.2021


Ответы (3)


Я думаю, вы можете использовать таблицу INSERTED для решения этой проблемы.

Вставленная таблица — это таблица, которая используется триггерами для хранения часто вставляемых записей в таблицы.

Таким образом, вы можете использовать то же самое в своем заявлении об обновлении, чтобы избежать этого.

update Product_TAB set OnShelfQuantity= Product_TAB.OnShelfQuantity - 
Ordertable.Quantity
FROM dbo.Product_TAB
INNER JOIN Ordertable  ON Ordertable.ProductID = Product_TAB.ProductID
INNER JOIN inserted INS ON INS.Order_ID=Ordertable.Order_ID
person Thiyagu    schedule 11.01.2021
comment
Нет причин присоединяться к таблице заказов - все, что вам нужно от нее, находится во вставленной таблице в триггере AFTER. - person SMor; 11.01.2021

В таблице inserted может быть несколько строк. И в этих строках может быть один и тот же продукт. Строка в целевой таблице обновляется только один раз в операторе update. Следовательно, вы хотите агрегировать данные до update:

create trigger dbo.Trigge
ON dbo.Ordertable
AFTER INSERT 
AS
BEGIN    
    update p
        set OnShelfQuantity= p.OnShelfQuantity - i.total_quantity
        from dbo.Product_TAB p JOIN
             (SELECT i.ProductId, SUM(i.Quantity) as total_quantity
              FROM inserted i
              GROUP BY i.ProductId
             ) i
             on i.ProductID = p.ProductID;
END;

Обратите внимание, что здесь используется только inserted, а не исходная таблица.

person Gordon Linoff    schedule 11.01.2021

Итак, проблема заключалась в том, что я вставлял новые строки, но с тем же идентификатором заказа. Вот почему он делал дополнительное вычитание, которое мне не требовалось. Итак, теперь мне нужно просто вставить новую строку, но с уникальным идентификатором OrderID. Спасибо всем, кто ответил выше!

person Muhammad Salman Ali    schedule 11.01.2021