Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / проблемма с рекурсивным вызовом тригера / 6 сообщений из 6, страница 1 из 1
09.10.2002, 14:28:42
    #32056750
keystop
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
проблемма с рекурсивным вызовом тригера
создал тригер для установки флага логического удаления. В таблице храниться структура папок (дерево). Ясно, что при удалении "более верхней папки" нужно удалить и все "нижние". Так вот пытаюсь "удалить" (а на самом деле обновить) одну из строк и вижу ошибку
Server: Msg 217, Level 16, State 1, Procedure tAU_RUBRIC, Line 16
Maximum stored procedure, function, trigger, or view nesting level exceeded (limit 32).

Код: 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.
CREATE TRIGGER tAU_RUBRIC
ON RUBRIC
AFTER UPDATE
AS
BEGIN

DECLARE @errnum   int,
	@errmsg   varchar( 255 )

if update(RubricDeleteDate) begin
	DECLARE @Status datetime

	SELECT TOP  1  @Status = RubricDeleteDate FROM inserted
	
	UPDATE RUBRIC
	SET RubricDeleteDate = @Status
	WHERE RubricParentID = (SELECT RubricID FROM inserted)
end

RETURN
ERROR:
	RAISERROR (@errnum, @errmsg,  10 )
	ROLLBACK TRANSACTION

END

 --и вот сам вызов
 
update rubric
set RubricDeleteDate = getdate()
where rubricID =  20 
...
Рейтинг: 0 / 0
09.10.2002, 15:06:44
    #32056767
проблемма с рекурсивным вызовом тригера
Есть такая глобальная переменная,
@@NESTLEVEL
которая показывает текущий уровень вложенности при рекурсивном вызове процедуры.

В вашем случае триггер должен выглядеть примерно так

Код: 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.
CREATE TRIGGER tAU_RUBRIC
ON RUBRIC
AFTER UPDATE
AS
BEGIN

DECLARE @errnum   int,
	@errmsg   varchar( 255 )

if @@NESTLEVEL <  [b]1  
begin[/b]
if update(RubricDeleteDate) begin
	DECLARE @Status datetime

	SELECT TOP  1  @Status = RubricDeleteDate FROM inserted
	
	UPDATE RUBRIC
	SET RubricDeleteDate = @Status
	WHERE RubricParentID = (SELECT RubricID FROM inserted)
end

end

RETURN
ERROR:
	RAISERROR (@errnum, @errmsg,  10 )
	ROLLBACK TRANSACTION

END


Если update вызывается из хранимой процедуры, то следует использовать условие
if @@NESTLEVEL < 2 и т.д.

т.е. решение получается не совсем универсальное
...
Рейтинг: 0 / 0
09.10.2002, 15:07:48
    #32056768
проблемма с рекурсивным вызовом тригера
Есть такая глобальная переменная,
@@NESTLEVEL
которая показывает текущий уровень вложенности при рекурсивном вызове процедуры.

В вашем случае триггер должен выглядеть примерно так

Код: 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.
CREATE TRIGGER tAU_RUBRIC
ON RUBRIC
AFTER UPDATE
AS
BEGIN

DECLARE @errnum   int,
	@errmsg   varchar( 255 )

if @@NESTLEVEL <  [b]1  
begin[/b]
if update(RubricDeleteDate) begin
	DECLARE @Status datetime

	SELECT TOP  1  @Status = RubricDeleteDate FROM inserted
	
	UPDATE RUBRIC
	SET RubricDeleteDate = @Status
	WHERE RubricParentID = (SELECT RubricID FROM inserted)
end

end

RETURN
ERROR:
	RAISERROR (@errnum, @errmsg,  10 )
	ROLLBACK TRANSACTION

END


Если update вызывается из хранимой процедуры, то следует использовать условие
if @@NESTLEVEL < 2 и т.д.

т.е. решение получается не совсем универсальное
...
Рейтинг: 0 / 0
09.10.2002, 15:22:23
    #32056773
Garya
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
проблемма с рекурсивным вызовом тригера
Сэры, проблема не в этом. Проблема в том, что флаг Update(SomeField) будет установлен даже в том случае, если фактически не было модифицировано ни одной записи. Он устанавливается просто по факту включения поля в перечень модифицируемых полей командой update, а сколько там записей фактически модифицировано (пусть даже и ни одной), до фени. Это раз. Триггер срабатывает на команду update вне зависимости от того, сколько записей фактически должно быть модифицировано (может быть, тоже ни одной). Это два. Из всего сказанного следует вывод, что прежде чем внутри триггера выдавать команду update, которая может привести к рекурсивному запуску триггеров, необходимо до этой команды поставить корректное условие выхода из рекурсии. Я обычно для этой цели использовал if exists(...), в котором проверял, есть ли хоть одна запись, которую необходимо модифицировать.
...
Рейтинг: 0 / 0
09.10.2002, 15:23:04
    #32056774
keystop
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
проблемма с рекурсивным вызовом тригера
Спасибо разобрался! не хватало условия выхода из рекурсии ))
Однако получается что болле 31 уровня папок через тригер ни как не удалить ((((
...
Рейтинг: 0 / 0
09.10.2002, 15:42:07
    #32056785
VVG_
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
проблемма с рекурсивным вызовом тригера
Можно рекурсию преобразовать в цикл, где-то это уже было здесь. По типу обхода графа в ширину.
...
Рейтинг: 0 / 0
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / проблемма с рекурсивным вызовом тригера / 6 сообщений из 6, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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