Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Как вызвать в процедуре саму себя? [D6, IB6.x, FireBird]


Кило ©   (2003-02-18 15:18:00) 

Мастера, помогите.
CREATE PROCEDURE GETPATHTOROOT (
id_parent INTEGER)
RETURNS (
name varchar(1000))
AS
DECLARE VARIABLE parent integer;
DECLARE VARIABLE child integer;
BEGIN
select name_operation, child_cnt, parent_id
from type_operation
where id_operation=:id_parent
into :name, :child, :parent;
if (:child=0) then
name = name + getpathtoroot(parent);
else
exit;
suspend;
END

Ругается, что нет getpathtoroot


Wolf   (2003-02-18 18:34:00) [1]

Да, но откуда мне знать какие элементы выбирать? Какие принадлежат этому куску дерева. Все-таки нужна рекурсия.

вот мой вариант

CREATE PROCEDURE test_tree(
AID_DEPARTMENT INTEGER,
ANAME_DEPARTMENT VARCHAR(512))
RETURNS (
ID_DEPARTMENT INTEGER,
NAME_DEPARTMENT VARCHAR(512))
AS
declare variable tid_department integer;
declare variable child integer;
declare variable tname_department varchar(512);
begin
for
select d.id, d.name, d.child from rf_department d
where d.parent=:aid_department
into :tid_department, :tname_department,:child
do
begin
if (aname_department is not null)
then tname_department=aname_department||"."||tname_department;
name_department=tname_department;
id_department=tid_department;
suspend;
if (child>0) then
for select id_department, name_department
from test_tree(:tid_department,:tname_department)
into :id_department, :name_department
do
suspend;
end
END


Кстати без поля child можно и обойтись, но если оно есть, то можно и возпользоваться, чтобы лишний раз не выполнять select


Wolf   (2003-02-18 18:20:00) [2]

Да, это почти то что тебе надо, единственно, вместо suspend, нужно выполнять конкатенциюб у них немного другое условие задачи.

То же и в моей задаче, только надо выполнить перебор всех элементов.

Но я думаю рекурсия будет оптимальней. Счас попробую проверить.


Val   (2003-02-18 17:38:00) [3]

>Кило (18.02.03 17:22)
вы, уважаемый, вероятно, не поняли смысла моего поста, посему зря нервничаете.


Кило   (2003-02-18 17:22:00) [4]

некоторым просто нужно обьяснить, что и как, а не кидаться с репликами типа: мы тут самые умные, а ты дурак и иди и смотри туда(f1, www... и т.д.)


Val   (2003-02-18 17:19:00) [5]

>Wolf © (18.02.03 17:06)
Попробуй :)..
Кило (18.02.03 17:11)
Пример из...

лихо, а? ;)
не то, что некоторые, даже f1 нажать лень.


Кило   (2003-02-18 17:11:00) [6]

Пример из http://www.ibase.ru/devinfo/treedb.htm CREATE PROCEDURE GETPARENTS (ID INTEGER)
RETURNS (DID INTEGER, OID INTEGER, NAME VARCHAR(30))
AS
BEGIN
WHILE (:ID > 0) DO /* ищем до корня */
BEGIN
SELECT O.ID, O.PARENT, O.NAME
FROM OBJECTS O
WHERE O.ID = :ID
INTO :DID, :OID, :NAME;
ID = :OID; /* код родителя для следующей выборки */
SUSPEND;
END
END


Wolf   (2003-02-18 17:06:00) [7]

Попробуй :)

Ты должен получить такой список

У Цех №1 и Цех №2 - есть родитель, который и есть тот исходный элемент.

Цех №1
Цех №1 / Участок №1
Цех №1 / Участок №1 / Блок А
Цех №1 / Участок №1 / Блок Б
Цех №1 / Участок №2
Цех №2
Цех №2 / Блок Р


Кило   (2003-02-18 16:58:00) [8]


> Вот там без рекурсии не обойтись.


Почему? вроде можно...


Wolf   (2003-02-18 16:38:00) [9]

C FB его нет. C IB есть.

У делал такую задачу:

Тоже нужен полный путь, но только от указанного элемента, всех "детей", "внуков", "правнуков" и т.д.

Вот там без рекурсии не обойтись.

Советую для тренировки сделать такую процедуру.


Johnmen   (2003-02-18 16:36:00) [10]

Пуск->Программы->InterBase->Documentation->SQL Reference Help
Примерно там............


Кило   (2003-02-18 16:26:00) [11]

А это где? :) я не нашел...


Johnmen   (2003-02-18 16:22:00) [12]

>Кило

А просто глянуть в SQL Reference Help ? :)))


Кило   (2003-02-18 16:19:00) [13]

2 wolf
Я уже по другому делаю через while и без рекурсии
А на счет ошибки ты прав, там я напутал... Ну учусь я только
Спасибо за то что помогаешь..


Wolf   (2003-02-18 16:15:00) [14]

Кстати, ты кажись напутал чего-то

if (:child=0) then
begin
execute procedure getpathtoroot(:parent)
returning_values(:t_name)
name = name||t_name;
end
else
exit;
suspend;


по моему надо так.


if (:parent=0) then
begin
execute procedure getpathtoroot(:parent)
returning_values(:t_name)
name = name||t_name;
end
suspend;


1. Ты идешь от конца до начала ветки, а начало, там где parent=0,
если он у тебя null- то поправь мое условие на :parent=nullили что там у тебя.
2. твой else exit;приведет к тому, что вызывать процедуру сможешь только через execute procedure, а select from- не пройдет.


Wolf   (2003-02-18 16:08:00) [15]

Можно и так

alter PROCEDURE GETPATHTOROOT (
id_parent INTEGER)
RETURNS (
name varchar(1000))
AS
DECLARE VARIABLE parent integer;
DECLARE VARIABLE child integer;
DECLARE VARIABLE t_name varchar(1000);
BEGIN
select name_operation, child_cnt, parent_id
from type_operation
where id_operation=:id_parent
into :name, :child, :parent;
if (:child=0) then
begin
execute procedure getpathtoroot(:parent)
returning_values(:t_name)
name = name||t_name;
end
else
exit;
suspend;
END


Wolf   (2003-02-18 15:59:00) [16]

Блин, а я и не заметил, что вызов процедуры неправильно написан, скопировал и все.

Тогда меняешь

if (:child=0) then
name = name + getpathtoroot(parent);


на
if (:child=0) then
select :name||name from getpathtoroot(:parent)
into :name;



Кило   (2003-02-18 15:54:00) [17]

Я как раз его и смотрю( www.codenet.ru/db/interbase), а там такого нет...


Johnmen   (2003-02-18 15:51:00) [18]

Еще бы неплохо глянуть в хелп по поводу вызова ХП.


Wolf   (2003-02-18 15:34:00) [19]

Надо создать данную процедуру с пустым телом, а затем выполнить alter.

set term ^;

CREATE PROCEDURE GETPATHTOROOT (
id_parent INTEGER)
RETURNS (
name varchar(1000))
AS
BEGIN
suspend;
END^

alter PROCEDURE GETPATHTOROOT (
id_parent INTEGER)
RETURNS (
name varchar(1000))
AS
DECLARE VARIABLE parent integer;
DECLARE VARIABLE child integer;
BEGIN
select name_operation, child_cnt, parent_id
from type_operation
where id_operation=:id_parent
into :name, :child, :parent;
if (:child=0) then
name = name + getpathtoroot(parent);
else
exit;
suspend;
END^


Наверх

Титульная страница Поиск, карта сайта Написать письмо