powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / При запуске процедуры из триггера она работает на два порядка дольше
4 сообщений из 4, страница 1 из 1
При запуске процедуры из триггера она работает на два порядка дольше
    #32054246
dishlo
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
У меня задача в столбце NOM integer null найти свободный номер. То есть если в столбце 1,2,2,4,5,7,6 то моя процедура должна вернуть 3 - свободный номер.
Написал я такую процедуру, поробовал как работает, на табличке с четырмя тысячами строк находит такой номер примерно за секунду.
Далее, запихиваю вызов этой процедуры в триггер на инсерт, вызываю для этой же таблицы и выясняю что она там работает 3-4 минуты.
Взял текст из процедуры, переделал и вставил на прямую в триггер. То же самое - 3-4 минуты.
В чем я неправ?


Код: 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.
CREATE  PROCEDURE dbo.spOS_SearchFreeNum
 @TABLE sysname,  --ПОЛУЧАЕТ ИМЯ ТАБЛИЦИ
 
 @Column sysname   -- КОЛОНКУ 
 
		  -- И ВОЗВРАЩАЕТ ПЕРВЫЙ СВОБОДНЫЙ НОМЕР НАЧИНАЯ С 1
 
AS 			 -- -1 КОД ОШИБКИ
 
BEGIN 			 -- ПРИМЕР: В СТОЛБЦЕ -2,-3,0,1,2,3,5,5,6  ПРОЦЕДУРА ВЕРНЕТ 4 - СВОБОДНЫЙ НОМЕР
 
SET NOCOUNT ON		 -- ПРИМЕР: В СТОЛБЦЕ 1,2,3,4,5,6 ПРОЦЕДУРА ВЕРНЕТ 7 - СВОБОДНЫЙ НОМЕР
 
  declare @type varchar( 10 ),@numeric_scale smallint,
 @NextNum int  --ПЕРЕМЕННАЯ В КОТОРУЮ ПОМЕЩАЕТЬСЯ СВОБОДНЫЙ НОМЕР ИЛИ -1 В СЛУЧАЕ ОШИБКИ
 
  set @type=null
  select @type=data_type, @numeric_scale=numeric_scale from information_schema.columns where table_name=@Table and column_name=@Column
if @type is null or @numeric_scale<> 0   -- если у колонки есть дробная часть то ретурн
 
  begin 
   raiserror('no table or column found', 10 , 5 )
   return - 1   --КОД ОШИБКИ -1
 
  end

DECLARE 
 @ExString varchar( 550 ),  -- НЕОБХОДИМА ДЛЯ ЗАПУСКА EXECUTE (ВЫКАЧАТЬ ВСЕ ЗНАЧЕНИЯ ИЗ ТАБЛИЦЫ
 
 @minni int
SET @ExString='SELECT DISTINCT '+ @COLUMN +' FROM '+@TABLE + ' WHERE '+ @COLUMN+'>0 '

create table #tmp_SearchFreeNum(ID int null, ID1 int IDENTITY( 1 , 1 ))
insert into #tmp_SearchFreeNum  -- ЗАПОЛНЕНИЕ ТАБЛИЦЫ
 
Exec(@ExString)


declare @ID int,@rowcount int
select @rowcount=count(*) from #tmp_SearchFreeNum; 

  set @minni=null
  select @minni=min(ID1) from #tmp_SearchFreeNum where ID1 not in (select ID from #tmp_SearchFreeNum)
  if @minni is null
   set @NextNum=scope_identity()+ 1   -- свободный номер это следующий в счетчике
 
  else Set @NextNum=@minni

end

DROP table #tmp_SearchFreeNum
Return @NextNum  -- все ок свободный номер найден
 

END
GO
...
Рейтинг: 0 / 0
При запуске процедуры из триггера она работает на два порядка дольше
    #32054250
Фотография toypaul
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ха! А у меня такая же задача толькос сложнее нужно искать для строковых колонок. Для числовых все просто (как мне кажется):

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
select top  1  start.key key_s,end.minkey key_e
from table start join 
(
 select min(key) minkey
 from table
 where key > start.key
) end
where key_e > key_s +  1 


Этот запрос найдет превый свободный интервал. Можно еще
Код: plaintext
order by start.key
добавить.

Топик-то как то ты назвал не в тему :)
...
Рейтинг: 0 / 0
При запуске процедуры из триггера она работает на два порядка дольше
    #32054256
Glory
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Можно чуть проще

Код: 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.
declare @myid int
create table #temp1(f1 int)

insert into #temp1 values( 1 )
insert into #temp1 values( 2 )
insert into #temp1 values( 4 )
insert into #temp1 values( 5 )
 --insert into #temp1 values(7)
 
 --insert into #temp1 values(8)
 
insert into #temp1 values( 10 )

 /*All "free"  id*/ 
select a.f1+ 1 
from #temp1 a 
left outer join #temp1 b on (b.f1) = (a.f1+ 1 )
where b.f1 is null

 /* First "free" id */ 
select top  1  @myid = a.f1
from #temp1 a 
left outer join #temp1 b on (b.f1) = (a.f1+ 1 )
where b.f1 is null
order by a.f1

select ISNULL(@myid,  0 ) +  1 
drop table #temp1
...
Рейтинг: 0 / 0
При запуске процедуры из триггера она работает на два порядка дольше
    #32054347
dishlo
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Я несколько ошарашен простотой идеи, но она отлична работает.
Остались сомнения насчет первого запроса, но в целом задумка ясна.
Остался академический интерес почему код процедуры быстро работает сам по-себе, но очень медленно в триггере?
Вопрос уже не конкретно по этому коду, а вообще.
...
Рейтинг: 0 / 0
4 сообщений из 4, страница 1 из 1
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / При запуске процедуры из триггера она работает на два порядка дольше
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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