Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
 Триггер для сбора остатков  [new]
Beaver
Member

Откуда:
Сообщений: 210
Данный триггер иногда работает неправильно, те собирает остатки некорректно
Помогите разобраться
ALTER       trigger tr_mat_ost on mat
for insert, update, delete not for replication
as

insert ost (matcode, sclad, kolvo)
select matcode, deban, kolvo = 0
from inserted
where
	inserted.prihod = 1 and
	not exists (select * from ost (holdlock) where matcode = inserted.matcode and 
		    sclad = inserted.deban)
	and isnull(inserted.matcode,0) <> 0
	and isnull(inserted.deban,0) <> 0
group by matcode, deban

update ost set
	kolvo = isnull(ost.kolvo,0) +  isnull(i.kolvo,0)
from  ost  (holdlock), 
(
	select matcode, deban, kolvo = sum(kolvo)
	from inserted
	where
		prihod = 1
		and isnull(matcode,0) <> 0
		and isnull(deban,0) <> 0
	group by matcode, deban
) i
where 
	ost.matcode = i.matcode and
	ost.sclad = i.deban

insert ost (matcode, sclad, kolvo)
select matcode, kredan, kolvo = 0
from inserted
where
	inserted.rashod = 1 and
	not exists (select * from ost (holdlock) where matcode = inserted.matcode and 
		    sclad = inserted.kredan)
	and isnull(inserted.matcode,0) <> 0
	and isnull(inserted.kredan,0) <> 0
group by matcode, kredan

update ost set
	kolvo =  isnull(ost.kolvo,0) - isnull( i.kolvo,0)
from  ost  (holdlock) ,
(
	select matcode, kredan, kolvo = sum(kolvo)
	from inserted
	where
		rashod = 1
		and isnull(matcode,0) <> 0
		and isnull(kredan,0) <> 0
	group by matcode, kredan
) i
where 
	ost.matcode = i.matcode and
	ost.sclad = i.kredan 

insert ost (matcode, sclad, kolvo)
select matcode, deban, kolvo = 0
from deleted
where
	deleted.prihod = 1 and
	not exists (select * from ost (holdlock) where matcode = deleted.matcode and 
		    sclad = deleted.deban)
	and isnull(deleted.matcode,0) <> 0
	and isnull(deleted.deban,0) <> 0
group by matcode, deban

update ost set
	kolvo = isnull(ost.kolvo,0) - isnull(d.kolvo,0)
from ost  (holdlock), 
(
	select matcode, deban, kolvo = sum(kolvo)
	from deleted
	where
		prihod = 1
		and isnull(matcode,0) <> 0
		and isnull(deban,0) <> 0
	group by matcode, deban
) d
where 
	ost.matcode = d.matcode and
	ost.sclad = d.deban 

insert ost (matcode, sclad, kolvo)
select matcode, kredan, kolvo = 0
from deleted
where
	deleted.rashod = 1 and
	not exists (select * from ost (holdlock) where matcode = deleted.matcode and 
		    sclad = deleted.kredan)
	and isnull(deleted.matcode,0) <> 0
	and isnull(deleted.kredan,0) <> 0
group by matcode, kredan

update ost set
	kolvo = isnull(ost.kolvo,0) +  isnull(d.kolvo,0)
from ost (holdlock),
(
	select matcode, kredan, kolvo = sum(kolvo)
	from deleted
	where
		rashod = 1
		and isnull(matcode,0) <> 0
		and isnull(kredan,0) <> 0
	group by matcode, kredan
) d
where 
	ost.matcode = d.matcode and
	ost.sclad = d.kredan 
go
20 май 04, 19:14    [691579]     Ответить | Цитировать Сообщить модератору
 Re: Триггер для сбора остатков  [new]
Beaver
Member

Откуда:
Сообщений: 210
Может ли триггер, вызванный одновременно из разных мест, изменять одни и те же строки в таблице OST?
Имеет ли смысл использовать в триггере
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE?
20 май 04, 20:51    [691712]     Ответить | Цитировать Сообщить модератору
 Re: Триггер для сбора остатков  [new]
Beaver
Member

Откуда:
Сообщений: 210
Может ли триггер, вызванный одновременно из разных мест, изменять одни и те же строки в таблице OST?
Имеет ли смысл использовать в триггере
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE?
20 май 04, 21:09    [691727]     Ответить | Цитировать Сообщить модератору
 Re: Триггер для сбора остатков  [new]
Crimean
Member

Откуда:
Сообщений: 13148
1.Что значит иногда?
2.SET писать нет необходимости
20 май 04, 21:46    [691743]     Ответить | Цитировать Сообщить модератору
 Re: Триггер для сбора остатков  [new]
Beaver
Member

Откуда:
Сообщений: 210
2 Crimean
По статистике неправильные результаты получаются примерно один раз на 1000 транзакций. Впечатление такое что во время выполнения Update таблицы ОСТ она изменяется другой транзакцией.
Пробовал во всех FROM для таблицы ОСТ писать (HOLDLOCK)
Не помогло
21 май 04, 07:41    [691938]     Ответить | Цитировать Сообщить модератору
 Re: Триггер для сбора остатков  [new]
Купер
Member [заблокирован]

Откуда: <went west>
Сообщений: 3145
Такое чувство будто триггер запускается в режиме level=read uncommitted
и таблица ОСТ "портится" инзертами из другого экземпляра этого триггера.
Думаю, стоит попробовать:
убрать все хинты и вписать SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
21 май 04, 11:37    [692511]     Ответить | Цитировать Сообщить модератору
 Re: Триггер для сбора остатков  [new]
Crimean
Member

Откуда:
Сообщений: 13148
А признак приход / расход не меняется?
Я бы проверку поставил :)
Или еще какое-нить из ключевых полей...
21 май 04, 11:44    [692535]     Ответить | Цитировать Сообщить модератору
 Re: Триггер для сбора остатков  [new]
Sjfx
Member

Откуда: Москва
Сообщений: 121
Н-да, ну дедлок тут можно представить, а ошибки с разбегу не видно,
но попробуй сначала группировать inserted.prihod_kol-insertded.rashod_kol + deleted.rashod_kol-deleted.prihod_kol .
Кстати, имеется UNIQUE INDEX on ost (matcode,sclad) ?
И стоит проверку влепить, что с клиента приходит, всегда ли prihod=1 при приходе и нет ли при этом расхода. И соотв-но такую же с расходом.
21 май 04, 12:50    [692821]     Ответить | Цитировать Сообщить модератору
 Re: Триггер для сбора остатков  [new]
Beaver
Member

Откуда:
Сообщений: 210
2 Sjfx
Спасибо за идею
Действительно, если вместо 6 insert и 6 update сделать по одному то сбоев будет меньше
21 май 04, 14:40    [693272]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить