В SQL Server нет триггеров для каждой строки.Вместо этого в триггере вы можете получить доступ к псевдотаблицам inserted
и deleted
.inserted
содержит вставленные строки или измененную версию строки для обновления и deleted
удаленные строки или версию строки перед обновлением.
Так что вам нужно использоватьчто-то вроде следующего, чтобы обновить сумму.Сначала он получает сумму для идентификатора для inserted
и аналог для deleted
, затем полное объединение результатов - здесь требуется полное объединение, поскольку не все идентификаторы обязательно находятся в обоих наборах, а затем обновляется main
.
UPDATE m
SET m.total = m.total + z.total
FROM main m
INNER JOIN (SELECT coalesce(x.main_fk, y.main_fk) main_fk,
coalesce(x.total, 0) - coalesce(y.total, 0) total
FROM (SELECT i.main_fk,
sum(i.amount) total
FROM inserted i
GROUP BY i.main_fk) x
FULL JOIN (SELECT d.main_fk,
sum(d.amount) total
FROM delete d
GROUP BY d.main_fk) y
ON y.main_fk = x.main_fk) z
ON z.main_fk = m.id;
(Возможно, вы хотите установить total
в main
на NULL
, если не осталось ни одной записи sub
. В приведенном выше запросе этого не делается, для этого потребуетсянекоторая дополнительная работа.)
Но физическое хранение таких цифр, которые могут быть вычислены из других, несет риск несоответствий.Если триггер отключен или не работает (должным образом) по другим причинам в течение определенного периода времени, изменения в таблице sub
(не правильно) не отражаются в таблице main
.У вас там будут ложные цифры, и, возможно, вы их даже не узнаете.
Я бы избегал таких вещей и выбирал бы вид вместо этого, если это возможно.(Писать тоже проще.;))
CREATE VIEW main_with_total
AS
SELECT m.id,
sum(s.amount) total
FROM main m
LEFT JOIN sub s
ON s.main_fk = m.id
GROUP BY m.id;
(Здесь вы получите NULL
как total
для идентификатора, в котором нет записей sub
. Если вы хотите 0, вместо этого изменитевыражение для total
до coalesce(sum(s.amount), 0)
.)