|
|
|
Рекурсия и Хранимая процедура
|
|||
|---|---|---|---|
|
#18+
Если Вас не затруднит, не укажете ли на ошибки, это конечно не VB форум, но если уж А, то и Б нужно говорить. Мне это только на пользу пойдет. Ошибки стиля рассматривать не будем, стиль у каждого разный и не все есть ошибка. (Хотя очень хочется :-) Также разбор полетов ограничим процедурой Tree, поскольку все остальное писано специально для тестирования и некоторые шероховатости не имеют большого значения. Начнем с того что Rs("F1.node_id") писать нельзя. Нужно Rs("node_id"). А если в запросе 2 node_id из разных таблиц, то извольте указать им различные псевдонимы и используйте последние как имена полей в VB. В противном случае всегда будете получать значение того node_id, что в коллекции Rs.Fields является первым. Далее будем полагать, что этой ошибки нет. Ваша основная ошибка заключается в стратегии обработки ошибок. У вас есть 2 строки вида on error resume next . При этом вторая, та что внутри while (стиль ужасен, извините, не удержался 8-) по большому счету не нужна. Начиная с первой такой строки и вплоть до выхода из процедуры, управление при ошибках будет передаваться на следующий оператор. В связи с этим возможны следующие сценарии. Первый селект вернул строку, не имеющую размера (size is null). Тогда строка allSize = allSize + RS("F1.size") вызывает ошибку (нельзя складывать Null и целое число). Но об этой ошибке вы не узнаете. И конечное значение будет не вполне корректно. (Хотя, возможно, null=0, есть правильно) Сценарий второй. Очередной cnn.Execute внутри цикла while. Завершился неудачей (Timeout expired, connection broken или еще какая-нибудь хрень). Вы об этом не узнаете (действует первый on error resume next). Выполнение продолжится. В строке nodeID = RS("node_id") происходит ошибка, ведь рекордсет не открыт, и nodeID остается равным 0. В последующем If мы закрываем закрытый рекордсет. Ошибка! А нам все пофиг, resume next, вашу мать. Дальше следует exit sub. Все это тихо и молча. В результате какая-то часть узлов не оказывает влияния на результат, а вы об этом ничего не знаете. Для вас процедура завершилась успешно. Ну и под занавес все таки об ошибке стиля. Какого хрена allSize глобальная переменная? Это же результат вычислений! Он должен возвращаться! Только так и без объяснений. (Извините, но если начну объяснять, то сразу вспомню, как мне пришлось отлаживать программулину, писанную одним товарищем, чтоб ему... там было 3247 глобальных переменных... говорить об этом могу только матом). ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 25.11.2002, 09:25:16 |
|
||
|
Рекурсия и Хранимая процедура
|
|||
|---|---|---|---|
|
#18+
По поводу процедуры Flint-San: Основная идея на первом шаге он помещает во временную таблицу id корневого узла. Далее в цикле он добавляет вершины, отцы которых уже находятся в таблице. При этом если вершина уже добавлена, то она не добавляется. Цикл продолжается, пока на очередном шаге не будет добавлено ни одной вершины. В таблице оказываются все узлы поддерева, суммарный вес вершин, которого и нужно подсчитать. Что и делается в последнем select. Кстати его процедура не учитывает вес корневого узла. Если это необходимо замениете Код: plaintext Код: plaintext Фактически это то же, что и в моем варианте №2. Короче, потому что начисто проигнорированна обработка ошибок. Ну и о временной таблице вам придется самому заботиться. Insert Into ее создаст конечно, а вот удаления или очистки там нет. В результате если вы в рамках одного коннекта вызовите процедуру дважды, для произвольной вершины и затем для ее потомка, то при первом вызове получите корректный результат, а при втором нет. Вернется вес первого поддерева, а не второго. Вот она прелесть глобальных данных! (это я к своему предыдущему постингу) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 25.11.2002, 09:40:10 |
|
||
|
Рекурсия и Хранимая процедура
|
|||
|---|---|---|---|
|
#18+
Следующий текст из предыдущего постинга: В результате если вы в рамках одного коннекта вызовите процедуру дважды, для произвольной вершины и затем для ее потомка, то при первом вызове получите корректный результат, а при втором нет. Вернется вес первого поддерева, а не второго. Вот она прелесть глобальных данных! (это я к своему предыдущему постингу) просьба считать несуществующим :-) Sorry, прогнал... ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 25.11.2002, 11:33:39 |
|
||
|
Рекурсия и Хранимая процедура
|
|||
|---|---|---|---|
|
#18+
Не думал, что это тема еще обсуждается. Chicago: Код правильный и ненужно его корректировать так как из задачи корневой узел это дирректорий, по вставляемым записям у дирректория Size IS NULL и размер определ-ся только по файлом. Теперь к вам вопрос, что даст ваше исправление? Код: plaintext 1. Код: plaintext 1. Правильно абсолютно ничего как для файла так и для каталога. Смысл вашего первого запроса, бесмысленен. У этой процедуры есть только один существенный недостаток, а именно ее скорость будет зависить от числа вложенных каталогов. Что же касается удаления временной таблицы... Процедура автоматически удаляет временную таблицу по выходу из нее. Chainiko: просто нашел всех детей(NodeId) по родителям(ParentID) при добавлении в таблицу проверяю есть ли там уже такой child или нет. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 25.11.2002, 12:38:49 |
|
||
|
Рекурсия и Хранимая процедура
|
|||
|---|---|---|---|
|
#18+
К Chicago: >>Правильно абсолютно ничего как для файла так и для >>каталога. Смысл вашего первого запроса, бесмысленен. Признаю свою ошибку , так как смыл вашего исправления позволит расчитать размер одного файла. Chainiko замени плиз код с Код: plaintext на Код: plaintext чтобы процедура могла расчитывать абсолютно все, включая и размер одного файла. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 26.11.2002, 07:35:45 |
|
||
|
Рекурсия и Хранимая процедура
|
|||
|---|---|---|---|
|
#18+
Я думаю пришли к консенсусу. 2Flint-San: Спасибо. Я от вас узнал для себя нечто новое: Что же касается удаления временной таблицы... Процедура автоматически удаляет временную таблицу по выходу из нее. If you create a local temporary table inside a stored procedure, the temporary table exists only for the purposes of the stored procedure; it disappears when you exit the stored procedure. Что-то редко такое стало происходить... Деградировать что-ли начинаю? ;-( ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 26.11.2002, 08:17:45 |
|
||
|
Рекурсия и Хранимая процедура
|
|||
|---|---|---|---|
|
#18+
Re Chicago Огромное спасибо. Очень признателен за указанные ошибки! Приятно, что Вы все очень подробно описали. Со всем согласен. On Error Resume Next - 2 раза действительно погорячился, а влепил его потому, что много надо было писать кода на проверки возвращаемых значений: есть ли записи в рекордсете, если есть, то поле NULL или нет, и только когда есть значение - инкрементировать. Еще раз благодарю. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 26.11.2002, 14:24:03 |
|
||
|
|

start [/forum/topic.php?fid=46&msg=32072305&tid=1818499]: |
0ms |
get settings: |
7ms |
get forum list: |
10ms |
check forum access: |
3ms |
check topic access: |
3ms |
track hit: |
77ms |
get topic data: |
6ms |
get forum data: |
2ms |
get page messages: |
30ms |
get tp. blocked users: |
1ms |
| others: | 194ms |
| total: | 333ms |

| 0 / 0 |
