Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / При запуске процедуры из триггера она работает на два порядка дольше / 4 сообщений из 4, страница 1 из 1
01.10.2002, 09:10:58
    #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
01.10.2002, 09:33:25
    #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
01.10.2002, 09:46:20
    #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
01.10.2002, 12:13:12
    #32054347
dishlo
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
При запуске процедуры из триггера она работает на два порядка дольше
Я несколько ошарашен простотой идеи, но она отлична работает.
Остались сомнения насчет первого запроса, но в целом задумка ясна.
Остался академический интерес почему код процедуры быстро работает сам по-себе, но очень медленно в триггере?
Вопрос уже не конкретно по этому коду, а вообще.
...
Рейтинг: 0 / 0
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / При запуске процедуры из триггера она работает на два порядка дольше / 4 сообщений из 4, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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