SQL Trigger - после вставки записи обновить баланс

У меня есть две таблицы браслеты (IDbracelet, BALANCE) и MoneyLoad (IDMoneyLoad, IDbracelet, Value) Я хочу обновить баланс браслета значением MoneyLoad каждый раз, когда значение вставляется в таблицу MoneyLoad (баланс = баланс + значение).

Я новичок в триггерах, поэтому не знаю, как действовать. Может ли кто-нибудь дать мне некоторое представление о том, как я должен это делать?

Обновлено: Я пробовал следующее, но когда я вставляю запись в MoneyLoad, появляется ошибка, говорящая, что баланс не может иметь значения NULL;

 if not exists (select 1 from Deleted) -- Insert Trigger
 BEGIN
        Update BRACELETS
    Set BALANCE = BALANCE + 
        (
        Select Sum(I.VALUE)
        From Inserted I 
        Where BRACELETS.IDBRACELET = I.IDBRACELET
        )
    From BRACELETS
END

Возможный дубликат SQL-триггер для вставки и обновления

kgzdev 21.11.2018 12:49

Хотели бы вы также обновлять браслеты при удалении или обновлении записей из MoneyLoad?

David Dubois 21.11.2018 13:41

Нет, вставлен только @DavidDubois

Kate 21.11.2018 13:48

В вашем заявлении об обновлении обновляется каждая строка браслетов. Для любой строки Bracelets, которая не соответствует ни одной строке Inserted, SUM равно NULL. Итак, вы добавляете NULL к существующему балансу, что приводит к NULL.

David Dubois 21.11.2018 14:24

Представление, которое вычисляет баланс, было бы гораздо лучшим подходом - особенно для очень неопытных. Расчетное значение баланса может быть сохранено при необходимости, но такие решения должны быть приняты позже. Для реализации триггеров требуется гораздо больше опыта, чем у вас сейчас.

SMor 21.11.2018 15:23
ReactJs | Supabase | Добавление данных в базу данных
ReactJs | Supabase | Добавление данных в базу данных
Это и есть ваш редактор таблиц в supabase.👇
Понимание Python и переход к SQL
Понимание Python и переход к SQL
Перед нами лабораторная работа по BloodOath:
0
5
1 007
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Что касается вашего сообщения об ошибке, я думаю, что BALANCE может иметь значение NULL. Вы проверили это (если ваш BALANCE имеет значение NULL для некоторого IDBRACELET). Если вы уверены, что ваш IDBRACELET всегда заполнен; вы можете попробовать этот запрос:

Update BRACELETS
Set BALANCE = ISNULL(BALANCE,0)+ 
    (
    Select Sum(I.VALUE)
    From Inserted I 
    Where BRACELETS.IDBRACELET = I.IDBRACELET
    )
From BRACELETS

Итак, если ваш IDBRACELET может быть нулевым, вы можете попробовать это:

Update BRACELETS
Set BALANCE = ISNULL(BALANCE,0) + 
    ISNULL(
    Select Sum(I.VALUE)
    From Inserted I 
    Where BRACELETS.IDBRACELET = I.IDBRACELET
    ),0)
From BRACELETS

Надеюсь, это поможет тебе.

Ответ принят как подходящий

Ваш триггер пытался обновить каждую строку таблицы браслетов. Для любой строки, которая не была включена во вставку, СУММ будет ПУСТО (NULL). Добавление NULL к балансу приводит к NULL. Вы хотите обновить только те записи, на которые ссылаются вставленные записи.

Помимо того, чтобы избежать этой проблемы с NULL, представьте, что ваша таблица Bracelets имеет миллион записей. Каждый раз, когда запись добавлялась в MoneyLoad, обновлялись все миллионы записей.

Кроме того, проверка НЕ ​​СУЩЕСТВУЕТ в триггере INSERT. DELETED всегда будет пустым.

Этот триггер может хорошо работать для INSERT, но вы можете подумать, что произойдет, если какие-либо записи будут обновлены или удалены.

create table Bracelets 
( IDBracelet nvarchar(30) not null primary key,
  Balance money not null default 0 );

create table MoneyLoad 
( IDBracelet nvarchar(30) not null 
  foreign key references Bracelets(IDBracelet),
  [Value] money not null );

go

create trigger tx_MoneyLoad on MoneyLoad 
for insert
as
begin
  if not exists (select 1 from Deleted) -- Insert Trigger
 BEGIN
        Update BRACELETS
    Set BALANCE = BALANCE + 
        (
        Select Sum(I.VALUE)
        From Inserted I 
        Where BRACELETS.IDBRACELET = I.IDBRACELET
        )
    where Bracelets.IDBracelet in ( select IDBracelet from Inserted )
END
end

go

insert into Bracelets ( IDBracelet ) values
( 'Bangle' ), ( 'Charm' ), ( 'Beaded' )

insert into MoneyLoad ( IDBracelet, [Value] ) values
( 'Bangle', 25 ), ( 'Charm', 10 ), ( 'Bangle', 20 )

select * from Bracelets

Результат:

IDBracelet                     Balance
------------------------------ ---------------------
Bangle                         45.00
Beaded                         0.00
Charm                          10.00

Другие вопросы по теме