powered by simpleCommunicator - 2.0.53     © 2025 Programmizd 02
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Как работать с рекурсиями в ХП? Киньте примером!
7 сообщений из 7, страница 1 из 1
Как работать с рекурсиями в ХП? Киньте примером!
    #32003710
tauras
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
НАДО НАПОЛНИТЬ РЕКОРДСЕТ В РЕКУРСИИ
...
Рейтинг: 0 / 0
Как работать с рекурсиями в ХП? Киньте примером!
    #32003712
Фотография SergSuper
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А может не стоит?

Написать то не сложно

create procedure #r @i int
as
declare @ii int
if @i<0 return
select @i
select @ii=@i-1
exec #r @ii
go

exec #r 20

Но глубина вложенности небольшая - 32 всего(попробуйте exec #r 40
), да и как-то ненадежно оно работает.
С рекурсией оно конечно выглядит красиво, но без неё всегда можно обойтись.
...
Рейтинг: 0 / 0
Как работать с рекурсиями в ХП? Киньте примером!
    #32003722
Фотография Garya
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
> С рекурсией оно конечно выглядит красиво, но без неё всегда можно обойтись.

Прямо-таки всегда? Дано:
Create table T (ID int primary key, Name varchar(50), Parent_ID int)
Смысл, думаю, понятен. Таблица для хранения дерева.
Нужно обеспечить удаление всех дочерних, внучатых, правнучатых... и т.д. записей при удалении узлов дерева.

Вариант 1. Заранее известно, что глубина дерева не превышает ограничения по вложенности рекурсивных триггеров (16 для 7.0)
Тогда, IMHO, самое правильное решение написать рекурсивный триггер:
create trigger T_OnDel on T
as
if exists(select T.ID from T, deleted D where T.Parent_ID=D.ID)
Delete from T
from T, deleted D where T.Parent_ID=D.ID
Это и изящно, и вообще...

Вариант 2. Заранее известно, что глубина дерева не превышает ограничения по вложенности хранимых процедур (32 для 7.0).
Триггер делается нерекурсивным. Но он вызывает хранимую процедуру, которая рекурсивна (текст писать не буду - интуитивно ясно).

Вариант 3. Глубина дерева вообще не ограничена. Увы, алгоритм раскраски дерева по своей природе рекурсивен. Рекурсия организуется с помощью стека. Выкручиваться, естественно придется без рекурсивных возможностей инструментария, поскольку уперлись в ограничения MS SQL Server. Делается все на циклах, но геморройно, поскольку нужно что-то вроде стека организовать самому (временная таблица).
Должен оговориться, что для варианта 3 есть нерекурсивный по природе вариант на голом цикле. На первом шаге цикла во временную таблицу переписываются ID и Parent_ID удаляемых записей (которую подали с клиента). На каждом следующем шаге цикла в эту таблицу переписываются ID и Parent_ID записей, которых пока что нет в этой таблице, но Paraent_ID которых in (select ID from #TemTable). И так до тех пор, пока переписывать будет нечего. В #TempTable получаем набор швутеификаторов всех записей, которые необходимо удалить - выдаем одну-единственную команду Delete - и всё. Да, алгоритм не рекурсивный. Но он еще и не оптимальный. Поскольку на каждом шаге цикла в перечень просматриваемых записей попадают те, которые уже раньше просмотрены (ID записей из верхних уровней дерева), и повторно просматривать которые нет смысла - а это дополнительный тормоз.
...
Рейтинг: 0 / 0
Как работать с рекурсиями в ХП? Киньте примером!
    #32003729
dmitry
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
"на каждом шаге цикла в перечень просматриваемых записей попадают те, которые уже раньше просмотрены (ID записей из верхних уровней дерева), и повторно просматривать которые нет смысла - а это дополнительный тормоз."
Ну если не устраивает именно это, то ведь моно иметь еще одну промежуточную таблицу, которая будет содержать ID записей, которые были добавлены в #TemTable непосредственно на предыдущем шаге... Ну а собсно инсертить их в #TemTable после того как они больше не нужны и делать в конце один большой Delete или Delete-ать их сразу- как больше нравится
...
Рейтинг: 0 / 0
Как работать с рекурсиями в ХП? Киньте примером!
    #32003736
Фотография SergSuper
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
2 Garya

В принципе я согласен. Но не стоит хранить данные так, чтобы это предполагало рекурсивную обработку.
Наверняка вы это читали:
http://sdm.viptop.ru/articles/sqltrees.html
...
Рейтинг: 0 / 0
Как работать с рекурсиями в ХП? Киньте примером!
    #32003772
Фотография alexeyvg
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Этот вопрос уже много раз обсуждался.
Ваш Вариант 3 с временной таблицой - самый оптимальный. На любой большой СУБД при больших объёмах данных он будет работать не в разы, а на порядки быстрее - секунды или минуты вместо часов или дней. Это следует из принципов организации БД - выполнить немного больших стейтментов (по к-ву уровней дерева) намного легче, чем много маленьких (по к-ву строк - миллион?).
Конечно, что-бы не было "каждом шаге цикла в перечень просматриваемых записей попадают те..." нужно в упомянутую временную таблицу добавить поле Level и включить его в условие.
Надо привыкнуть, что рекурсия в SQL - самый "неизящный" метод программирования, это наследие процедурно-объектного мышления: SQL - не С или С++.
...
Рейтинг: 0 / 0
Как работать с рекурсиями в ХП? Киньте примером!
    #32003774
Фотография Garya
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Честно говоря, не знаю как именно в SQL Server рекурсивность сказывается на быстродействии. Во всех остальных инструментариях отрицательно. Это связано с необходимостью сохранения в стеке всех локальных переменных. Возможно, в SQL ситуация не просто аналогичная, но соображения alexeyvg являются дополнительным и более важным фактором, сказывающимся на быстродействии.
Тем не менее, не могу согласиться с тем, что рекусия - самый неизящный стиль. IMHO, как раз наоборот. Посмотри на текст рекурсивного триггера (в 2 строчки) и сравни с текстом аналогичного нерекурсивного скрипта. В этом плане я скорее соглашусь со мнением SergSuper.
По поводу того, что рекурсия - это наследие процедурного мышления (в смысле "пережиток") тоже не могу согласиться. Современный Transact-SQL содержит операторы Exec (аналог Call), If, While, механизмы пошаговых вычислений, локальные переменные. Это все атрибуты процедурного программирования. И появились они не в первых версиях T-SQL с последующим отмиранием, а наоборот. Даже термин "stored procedure" говорит сам за себя (а не "stored query"). И это не пережиток, а веление времени. Грани между процедурным языком и языком запросов постепенно стираются. В версиях 7.0 и 2000 SQL-сервера получило развитие обращение объектам БД в контексте объектной модели (родитель.объект-свойство). Я не удивлюсь, если в будущем увижу диалекты T-SQL, поддерживающие множественное наследие и перегрузку операций. IMHO, поезд катится не просто к процедурному, а еще и к объектно-ориентированному. Это неизбежный процесс, если речь идет о переносе бизнес-логики на сервер. Отказавшись от процедурного мышления, далеко не все можно реализовать операциями базовой реляционной алгебры.
Также не могу согласиться, что реляционное мышление - это пик человеческой мысли. Графы, деревья продолжают использоваться вместе с табличными представлениями и отмирать не собираются. Когда-то на MUMPS (иерархическая СУБД) программисты ломали голову над тем, как выполнять агрегатные функции и произвольно задаваемые объединения по таблично-подобным данным. Теперь более молодое поколение ломает голову над тем, как с помощью табличных структур представить граф или дерево так, чтобы с ним было удобно работать методами реляционной алгебры. Я уверен, что следующее поколение сможет работать и стем, и с другим с одинаковой легкостью, получив настоящий объектно-ориентированный инструментарий.
...
Рейтинг: 0 / 0
7 сообщений из 7, страница 1 из 1
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Как работать с рекурсиями в ХП? Киньте примером!
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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