powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Можно ли оптимизировать триггер?
9 сообщений из 9, страница 1 из 1
Можно ли оптимизировать триггер?
    #32067852
Wicky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Наваял что-то, но оно тормозит немного...
мне то что в принципе, а пользователи ругаются :)
можно ли это дело как-то оптимизировать?
(Взаимодействие идет через ODBC.)

по такому же принципу еще и на INSERT и DELETE...
порекомендуйте, пожалуйста, что нибудь.

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
150.
151.
152.
153.
154.
155.
156.
157.
CREATE TRIGGER updTable_ИзменениеПроданоЗаМесяцНаНовоеКоличествоТовара
ON dbo.СтрокиКороткойНакладной
FOR UPDATE
AS

DECLARE @CardID int, @OldDilerCardID int, @NewDilerCardID int, @SalerID int, @BuyerID int, @ShortAccountID int, @AccountID int, @Quantity int,
                  @OldQuantity int, @NewQuantity int, @DateOfShortAccount datetime, @DayOfChanges nvarchar( 255 ), @strSQL nvarchar ( 1024 ), 
@CurrentCostPriceOfDilerCard_RUB money, @CurrentValueOfCourseUSD money, @CurrentOurPriceOfDilerCard_RUB money


SET NOCOUNT ON

	SELECT @OldDilerCardID = КодТовара, @OldQuantity = Количество
	FROM deleted

	SELECT @NewDilerCardID = КодТовара, @NewQuantity = Количество, @ShortAccountID = КодКороткойНакладной
	FROM inserted

	 /*найдем короткую накладную, которой принадлежит данная строка короткой накладной*/ 
	SELECT @DateOfShortAccount = ДатаВыпискиНакладной, @AccountID = НомерУниверсальногоЛиста
	FROM КороткаяНакладная 
	WHERE (((КодКороткойНакладной)=@ShortAccountID))

	 /*Конвертнем дату в день (12.10.2002 станет 12)*/ 
	Set @DayOfChanges = convert(nvarchar( 255 ),Day(@DateOfShortAccount))

	 /*найдем КодТовара, который соответствовал данному КодуТовараДилера*/ 
	SELECT @CardID = КодТовара
	FROM ТоварыДилера 
	WHERE (((КодТовараДилера)=@OldDilerCardID))

BEGIN
 /*начало блока*/ 

 /*Проверка есть ли строка с данным товаром в учетном листе закупок*/ 
IF 	(EXISTS
    (
	SELECT * 
	FROM ПроданоЗаМесяц 
	WHERE (((ПроданоЗаМесяц.КодТовара)=@CardID) AND ((ПроданоЗаМесяц.НомерУниверсальногоЛиста)=@AccountID))
    )
	)
     BEGIN


	 /*Склеим строку SQL на запуск UPDATE*/ 
	Set @strSQL = N'UPDATE ПроданоЗаМесяц SET ПроданоЗаМесяц.[' + @DayOfChanges + N'] = ПроданоЗаМесяц.[' + @DayOfChanges + N'] - ' + convert(nvarchar( 255 ),@OldQuantity) + N' WHERE (((ПроданоЗаМесяц.КодТовара)=' + convert(nvarchar( 255 ),@CardID) + N') AND ((ПроданоЗаМесяц.НомерУниверсальногоЛиста)=' + convert(nvarchar( 255 ),@AccountID) + N'))'
	exec (@strSQL)


     END

 /*если же нет в закупочном учетном листе записи с таким товаром, то ничего не делаем*/ 

 /*конец блока*/ 
END




	 /*найдем КодТовара, который соответствует данному КодуТовараДилера*/ 
	SELECT @CardID = КодТовара
	FROM ТоварыДилера 
	WHERE (((КодТовараДилера)=@NewDilerCardID))

BEGIN
 /*начало блока*/ 

 /*Проверка есть ли строка с данным товаром в учетном листе закупок*/ 
IF 	(EXISTS
    (
	SELECT * 
	FROM ПроданоЗаМесяц 
	WHERE (((ПроданоЗаМесяц.КодТовара)=@CardID) AND ((ПроданоЗаМесяц.НомерУниверсальногоЛиста)=@AccountID))
    )
	)
     BEGIN
	 /*Склеим строку SQL на запуск UPDATE*/ 
	Set @strSQL = N'UPDATE ПроданоЗаМесяц SET ПроданоЗаМесяц.[' + @DayOfChanges + N'] = ПроданоЗаМесяц.[' + @DayOfChanges + N'] + ' + convert(nvarchar( 255 ),@NewQuantity) + N' WHERE (((ПроданоЗаМесяц.КодТовара)=' + convert(nvarchar( 255 ),@CardID) + N') AND ((ПроданоЗаМесяц.НомерУниверсальногоЛиста)=' + convert(nvarchar( 255 ),@AccountID) + N'))'
	exec (@strSQL)
     END

 /*если же нет в закупочном учетном листе записи с таким товаром, то ничего не делаем*/ 
ELSE
     BEGIN
	INSERT ПроданоЗаМесяц (КодТовара, НомерУниверсальногоЛиста) 
	VALUES (@CardID, @AccountID)

	 /*Склеим строку SQL на запуск UPDATE*/ 
	Set @strSQL = N'UPDATE ПроданоЗаМесяц SET ПроданоЗаМесяц.[' + @DayOfChanges + N'] = ПроданоЗаМесяц.[' + @DayOfChanges + N'] + ' + convert(nvarchar( 255 ),@NewQuantity) + N' WHERE (((ПроданоЗаМесяц.КодТовара)=' + convert(nvarchar( 255 ),@CardID) + N') AND ((ПроданоЗаМесяц.НомерУниверсальногоЛиста)=' + convert(nvarchar( 255 ),@AccountID) + N'))'
	exec (@strSQL)
     END

 /*конец блока*/ 
END


 /*Возьмем курс дня выписки накладной*/ 
SELECT @CurrentValueOfCourseUSD = КурсДолл
FROM КурсДолл
WHERE Дата = @DateOfShortAccount


 /*-----------------------------------вычитаем все OLD-----------------------------------*/ 

 /*Получим значение закупочной цены карты в рублях на сегодняшний день*/ 
SELECT @CurrentOurPriceOfDilerCard_RUB = 
					Case
							when [ЦенаЗакупки] =  0  then [ЦенаЗакупкиИсходная] * @CurrentValueOfCourseUSD
							when [ЦенаЗакупки] <>  0  then [ЦенаЗакупки]
					End
FROM Товары INNER JOIN ТоварыДилера ON (Товары.КодТовара = ТоварыДилера.КодТовара) 
WHERE (([КодТовараДилера] = @OldDilerCardID))


 /*Получим значение продажной цены карты в рублях на сегодняшний день*/ 
SELECT @CurrentCostPriceOfDilerCard_RUB = 
					Case
							when [ЦенаПрРуб] =  0  then [ЦенаПрДол] * @CurrentValueOfCourseUSD
							when [ЦенаПрРуб] <>  0  then [ЦенаПрРуб]
					End
FROM [ТоварыДилера] 
WHERE (([КодТовараДилера] = @OldDilerCardID))

 /*Необходимо изменить стоимость накладной на сумму составляющую стоимость карт текущей строки*/ 
UPDATE КороткаяНакладная
Set СуммаПоНакладнойRUB = СуммаПоНакладнойRUB - (@OldQuantity * @CurrentCostPriceOfDilerCard_RUB), 
ЗакСтПоНакладнойRUB = ЗакСтПоНакладнойRUB - (@OldQuantity * @CurrentOurPriceOfDilerCard_RUB) 
WHERE (((КодКороткойНакладной)=@ShortAccountID))


 /*-----------------------------------прибавляем все NEW-----------------------------------*/ 

 /*Получим значение закупочной цены карты в рублях на сегодняшний день*/ 
SELECT @CurrentOurPriceOfDilerCard_RUB = 
					Case
							when [ЦенаЗакупки] =  0  then [ЦенаЗакупкиИсходная] * @CurrentValueOfCourseUSD
							when [ЦенаЗакупки] <>  0  then [ЦенаЗакупки]
					End
FROM Товары INNER JOIN ТоварыДилера ON (Товары.КодТовара = ТоварыДилера.КодТовара) 
WHERE (([КодТовараДилера] = @NewDilerCardID))


 /*Получим значение продажной цены карты в рублях на сегодняшний день*/ 
SELECT @CurrentCostPriceOfDilerCard_RUB = 
					Case
							when [ЦенаПрРуб] =  0  then [ЦенаПрДол] * @CurrentValueOfCourseUSD
							when [ЦенаПрРуб] <>  0  then [ЦенаПрРуб]
					End
FROM [ТоварыДилера] 
WHERE (([КодТовараДилера] = @NewDilerCardID))

 /*Необходимо изменить стоимость накладной на сумму составляющую стоимость карт текущей строки*/ 
UPDATE КороткаяНакладная
Set СуммаПоНакладнойRUB = СуммаПоНакладнойRUB + (@NewQuantity * @CurrentCostPriceOfDilerCard_RUB), 
ЗакСтПоНакладнойRUB = ЗакСтПоНакладнойRUB + (@NewQuantity * @CurrentOurPriceOfDilerCard_RUB)
WHERE (((КодКороткойНакладной)=@ShortAccountID))
...
Рейтинг: 0 / 0
Можно ли оптимизировать триггер?
    #32067858
Genady
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Насчет оптимизации не знаю, но триггер с типичной ошибкой. Вы его написали с расчетом, что в таблицах inserted и deleted всегда одна запись, на самом деле их может быть много.
...
Рейтинг: 0 / 0
Можно ли оптимизировать триггер?
    #32067891
Фотография MiCe
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
если уж надо чтоб триггер работал только с одно вставляемой строкой
добавте в начало проверку на количество строк тип такого...
select @c = count(*) from inserted
if @c>1
begin
rollback
-- RAISERROR ( 'блаблабалэ...' )
return 1
end
...
Рейтинг: 0 / 0
Можно ли оптимизировать триггер?
    #32067898
fima
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
по моему правильней будет не
Код: plaintext
1.
2.
select @c = count(*) from inserted 
if @c> 1  

а
Код: plaintext
1.
if exists(select * from inserted)

еще можно проверять @@rowcount, но по моему, нужно следить тогда за set nocount on, но в этом не уверен... если неправ поправьте...
А по поводу оптимизации... дело скорее не в коде, хотя как мне кажется, лучше бы использовать подзапросы, а не выбирать в переменную, и потом подставлять в запрос, а неплохо бы посмотреть индексы на таблицы... Я думаю выборка очень долго идет.
...
Рейтинг: 0 / 0
Можно ли оптимизировать триггер?
    #32067936
nandji
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ХМ ...
...
Рейтинг: 0 / 0
Можно ли оптимизировать триггер?
    #32068158
Фотография MiCe
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
я бы часть логики вынес в SP....
и отказался бы от exec.... заменил бы на if else....
...
Рейтинг: 0 / 0
Можно ли оптимизировать триггер?
    #32068283
Wicky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
2 MiCe:

А можно поподробнее вот с этого места, очень рад бы получить рекомендации...
хотя б теоретические
...
Рейтинг: 0 / 0
Можно ли оптимизировать триггер?
    #32068411
Фотография MiCe
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Set @strSQL = N'UPDATE ПроданоЗаМесяц SET ПроданоЗаМесяц.[' + @DayOfChanges + N'] = ПроданоЗаМесяц.[' + @DayOfChanges + N'] - ' + convert(nvarchar(255),@OldQuantity) + N' WHERE (((ПроданоЗаМесяц.КодТовара)=' + convert(nvarchar(255),@CardID) + N') AND ((ПроданоЗаМесяц.НомерУниверсальногоЛиста)=' + convert(nvarchar(255),@AccountID) + N'))'
exec (@strSQL)
вынести во внешнию процу и разбить на if else.....
if @DayOfChanges = bla
UPDATE ПроданоЗаМесяц SET ПроданоЗаМесяц. bla = ПроданоЗаМесяц. bla - @OldQuantity WHERE ПроданоЗаМесяц.КодТовара=@CardID AND ПроданоЗаМесяц.НомерУниверсальногоЛиста=@AccountID
else if @DayOfChanges = bla1
.............
...
Рейтинг: 0 / 0
Можно ли оптимизировать триггер?
    #32068434
ALk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
ALk
Гость
дабы не тормозить сервер выполнением такого громоздкого подсчета каждый раз после обновления записи я бы сделал бы из триггера запись в служебной табличке - имя процедуры которую нужно запустить для обновления данных и планируемое время запуска - например текущее время + nn секунд .
если в течении этого времени происходят еще изменения - запись обновляется с новой отсрочкой по времени.

а запуском по этой таблице может заниматься процедура запускаемая переодически из агента (или циклически запущенная с ожиданием по времени ???)

наверное можно создавать задания для агента и редактировать их но советовать не могу по тому что сам не пробовал, мысль пришла пока писал это...
...
Рейтинг: 0 / 0
9 сообщений из 9, страница 1 из 1
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Можно ли оптимизировать триггер?
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]