powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Firebird, InterBase [игнор отключен] [закрыт для гостей] / Interbase VS Firebird Heeeeeelp!
39 сообщений из 39, показаны все 2 страниц
Interbase VS Firebird Heeeeeelp!
    #32230886
Gallagher
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Народ, сидевший за IB, помогите справиться. Глюка такая: есть хранимая процедура которая возвращает несколько строк. В дебаггере (IBExpert 2.5.0.53) всё работает путём, а если скриптом
Код: plaintext
select * from Proc_Name(Param) 

или из Query дельфей то она ничего не возвращает. Встречаю такую траблу неоднократно. Стоит Delphi 6, Firebird 1, 1.5, Interbase 6.5, win2k, 98. Пробовали во всех возможных сочетаниях.
...
Рейтинг: 0 / 0
Interbase VS Firebird Heeeeeelp!
    #32230914
alex_k
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
давай свой ХП и свой параметр... заодно дельфевый код давай, как данные их хп читаешь....
...
Рейтинг: 0 / 0
Interbase VS Firebird Heeeeeelp!
    #32230927
Фотография Dnico
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
И какое сообщение вылетает ?
А то уж совсем не понятно что происходит ...
...
Рейтинг: 0 / 0
Interbase VS Firebird Heeeeeelp!
    #32230937
Фотография Zmeishe
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Чтобы вызвать из Дельфей, по моему нужно двоеточие, для начала!
select * from Proc_Name( : Param)
...
Рейтинг: 0 / 0
Interbase VS Firebird Heeeeeelp!
    #32230942
Gallagher
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Тока не пугайтесь !)
Это всё надо для организации упорядоченного дерева в одной таблице Tree , где
ID - понятно
PARENT_ID - тоже понятно (у корневых элементов null)
NODE_NAME - просто строка
NODE_TYPE - тип узла (D - директорий, F - папка)
NODE_ORDER - порядок элемента

Код: 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.
CREATE PROCEDURE GET_TREE (
    PARENT_ID INTEGER)
RETURNS (
    NODE_ID INTEGER,
    NODE_PARENT_ID INTEGER,
    NODE_NAME VARCHAR( 11 ),
    NODE_TYPE VARCHAR( 1 ),
    NODE_ORDER INTEGER)
AS
DECLARE VARIABLE J INTEGER;
DECLARE VARIABLE I INTEGER;
begin
  /*вытащим папки */ 
 for
  select node_id, node_parent_id, node_name, node_type, node_order
  from tree
  where (node_type = 'D') and
        (node_parent_id = :PARENT_ID)
  order by node_order
  into :node_id, :node_parent_id, :node_name, :node_type, :node_order

 do
  begin
   /* выкинем в программу вытащенную папку*/ 
  suspend;
   /* для каждой папки найдём дерево, для которого она - вершина*/ 
  J = :node_id;
  select count(*) from tree b where (b.node_parent_id=:J) into :i;
  if (i >  0 ) then begin
                  for
                    select node_id, node_parent_id, node_name, node_type, node_order
                    from GET_TREE(:J)
                    into  :node_id, :node_parent_id, :node_name, :node_type, :node_order
                  do
                    suspend;
                  end
  end
  
  /*вытащим файлы*/ 
  for
  select node_id, node_parent_id, node_name, node_type, node_order
  from tree
  where (node_type = 'F') and
        (node_parent_id = :PARENT_ID)
  order by node_order
  into :node_id, :node_parent_id, :node_name, :node_type, :node_order
 do suspend;
end


Дельфёвый код простой:
Код: plaintext
1.
2.
3.
if IBQuery1.Active then IBQuery1.Close;
IBQuery1.Prepare;
IBQuery1.Open;


В Query1.SQL
Код: plaintext
1.
select * from GET_TREE(null)


Проблема снимается если вызывать GET_TREE не с NULL. Но интересно получить именно с корневыми разделами.
...
Рейтинг: 0 / 0
Interbase VS Firebird Heeeeeelp!
    #32230960
Фотография Zmeishe
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ну так если ты прередаёшь NULL, то вытаскивай не (node_parent_id = :PARENT_ID), а (node_parent_id is null ).

И вообще проверь, есть там такие node_parent_id, которые null .
...
Рейтинг: 0 / 0
Interbase VS Firebird Heeeeeelp!
    #32230968
alex_k
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
во-во
0 и null разные весчи...
все операции с null дают null

так что вот, принимай к сведению
...
Рейтинг: 0 / 0
Interbase VS Firebird Heeeeeelp!
    #32230975
Gallagher
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
ПИП!!!! Мать его IB!!!!! Убивай топик!
Забыл, млин, что ИБ не умеет так сравнивать:
A=null;
B=null;
if (a=b) then зен зен зен мать его никогда он не будет !)
Всем сенкс
...
Рейтинг: 0 / 0
Interbase VS Firebird Heeeeeelp!
    #32230995
Gallagher
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Вобщем конечно не фонтан, но жить можно
Избавился разнесением на две процы (если подскажите как короче буду премного благодарен)

блин код пришлось дублировать, не люблю я это :(

Проца 1: GetTree - возвращает всё дерево целиком

Код: 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.
CREATE PROCEDURE GET_TREE
RETURNS (
    NODE_ID INTEGER,
    NODE_PARENT_ID INTEGER,
    NODE_NAME VARCHAR( 11 ),
    NODE_TYPE VARCHAR( 1 ),
    NODE_ORDER INTEGER)
AS
DECLARE VARIABLE J INTEGER;
DECLARE VARIABLE I INTEGER;
begin
  /*вытащим папки */ 
 for
  select node_id, node_parent_id, node_name, node_type, node_order
  from tree
  where (node_type = 'D') and
        (node_parent_id is NULL)
  order by node_order
  into :node_id, :node_parent_id, :node_name, :node_type, :node_order

 do
  begin
   /* выкинем в программу вытащенную папку*/ 
  suspend;
   /* для каждой папки найдём дерево, для которого она - вершина*/ 
  J = :node_id;
  select count(*) from tree b where (b.node_parent_id=:J) into :i;
  if (i >  0 ) then begin
                  for
                    select node_id, node_parent_id, node_name, node_type, node_order
                    from GET_SUB_TREE(:J)
                    into  :node_id, :node_parent_id, :node_name, :node_type, :node_order
                  do
                    suspend;
                  end
  end
  
  /*вытащим файлы*/ 
  for
  select node_id, node_parent_id, node_name, node_type, node_order
  from tree
  where (node_type = 'F') and
        (node_parent_id is NULL)
  order by node_order
  into :node_id, :node_parent_id, :node_name, :node_type, :node_order
 do suspend;
end


Проца 2: GetSubTree(parent_id) - возвращает поддерево с вершиной в ID=parent_ID

Код: 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.
CREATE PROCEDURE GET_SUB_TREE (
    PARENT_ID INTEGER)
RETURNS (
    NODE_ID INTEGER,
    NODE_PARENT_ID INTEGER,
    NODE_NAME VARCHAR( 11 ),
    NODE_TYPE VARCHAR( 1 ),
    NODE_ORDER INTEGER)
AS
DECLARE VARIABLE J INTEGER;
DECLARE VARIABLE I INTEGER;
begin
  /*вытащим папки */ 
 for
  select node_id, node_parent_id, node_name, node_type, node_order
  from tree
  where (node_type = 'D') and
        (node_parent_id = :PARENT_ID)
  order by node_order
  into :node_id, :node_parent_id, :node_name, :node_type, :node_order

 do
  begin
   /* выкинем в программу вытащенную папку*/ 
  suspend;
   /* для каждой папки найдём дерево, для которого она - вершина*/ 
  J = :node_id;
  select count(*) from tree b where (b.node_parent_id=:J) into :i;
  if (i >  0 ) then begin
                  for
                    select node_id, node_parent_id, node_name, node_type, node_order
                    from GET_SUB_TREE(:J)
                    into  :node_id, :node_parent_id, :node_name, :node_type, :node_order
                  do
                    suspend;
                  end
  end
  
  /*вытащим файлы*/ 
  for
  select node_id, node_parent_id, node_name, node_type, node_order
  from tree
  where (node_type = 'F') and
        (node_parent_id = :PARENT_ID)
  order by node_order
  into :node_id, :node_parent_id, :node_name, :node_type, :node_order
 do suspend;
end
...
Рейтинг: 0 / 0
Interbase VS Firebird Heeeeeelp!
    #32231092
alex_k
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
избавься от порочной практики использования NULL
замени на 0 везде, и поле объяви not null (но не наоборот, а то огребешься)
...
Рейтинг: 0 / 0
Interbase VS Firebird Heeeeeelp!
    #32231104
Фотография Zmeishe
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Не только короче, но и по скорости быстрее будет так:
1. Все NULL замени на 0
2. Верхнее звено замкни само на себя т.е. ID = 0 и ID_PARENT = 0
3. Построй внешний ключ FK ID_PARENT на ID этой же таблицы. Таким образом никто не сможет удалить родителя пока есть потомки. IB не даст.
4. Добавь дополнительный столбец количество потомков KID_COUNT integer. Не надо будет каждый раз сажать скорость процедуры select count(*)!
5. Напиши три триггера

5.1 AFTER INSERT
update tree
set kid_count = kid_count + 1
where id = new.id_parent

5.2 AFTER APDATE
if(old.id_parent <> new.id_parent) then begin
update tree
set kid_count = kid_count + 1
where id = new.id_parent

update tree
set kid_count = kid_count - 1
where id = old.id_parent
end

5.3 AFTER DELETE
update tree
set kid_count = kid_count - 1
where id = old.id_parent
5.4 Триггеры проверь внимательно, я их воспроизвёл по памяти не глядя в свою базу!
6. Процедуру переделай. Теперь сам сообразишь как. NULL больше нет.
7. Наслаждайся скоростью.
...
Рейтинг: 0 / 0
Interbase VS Firebird Heeeeeelp!
    #32231151
Gallagher
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Спасиба огромное, друзья, но из всего приму тока создать корень с ID=PARENT_ID=0, ибо Fk уже висит, а вводить поле количество детей - грозит громадными тормозами триггеров при перемещении ветвей друг в друга (а у меня их с полторы тысячи)
...
Рейтинг: 0 / 0
Interbase VS Firebird Heeeeeelp!
    #32231180
Фотография Dnico
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Смотрю я на текст ХП и диву даюсь ... А слабо GET_TREE в 6 строках ?
...
Рейтинг: 0 / 0
Interbase VS Firebird Heeeeeelp!
    #32231211
Gallagher
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Да есть тут с десяток идей....
...
Рейтинг: 0 / 0
Interbase VS Firebird Heeeeeelp!
    #32231233
Gallagher
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
В скорости ты уж точно не выиграешь... вроде бы :(
...
Рейтинг: 0 / 0
Interbase VS Firebird Heeeeeelp!
    #32231239
Фотография Zmeishe
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Gallagher
> грозит громадными тормозами триггеров при перемещении ветвей друг в друга (а у меня их с полторы тысячи)

При перемещении одной ветви в другую триггер отработает всего две операции чтения, да и то по первичному ключу!!!

Dnico
> А слабо GET_TREE в 6 строках ?

Оно конечно можно и в одну, но каждый привык к своему стилю оформления текста процедур, ну чтобы читаемо было.
А вот по объёму текста в целом, то раза в три меньше это легко!

Можем обменяться алгоритмами - очень даже интересно. Но я не раньше понедельника. У меня эта процедура на домашнем компе.
...
Рейтинг: 0 / 0
Interbase VS Firebird Heeeeeelp!
    #32231245
Gallagher
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Сорри, насчёт триггера протупил. Ты прав
...
Рейтинг: 0 / 0
Interbase VS Firebird Heeeeeelp!
    #32231276
Фотография Dnico
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Есть вот такой простой вариант .... может подойдет?

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
CREATE PROCEDURE GET_TREE (
    PARENTID VARCHAR( 10 ))
RETURNS (
    NODE_ID VARCHAR( 10 ),
    NODE_PARENTID VARCHAR( 10 ),
    NODE_ISFOLDER SMALLINT,
    NODE_NAME VARCHAR( 100 ))
AS
BEGIN
   /* Начало процедуры */ 
  FOR SELECT ID, PID, ISF, NAME FROM GOODS WHERE PID = :PARENTID ORDER BY PID, NAME
      INTO :NODE_ID, :NODE_PARENTID, :NODE_ISFOLDER, :NODE_NAME DO BEGIN
      SUSPEND;
      IF (:NODE_ISFOLDER =  1 ) THEN
        FOR SELECT NODE_ID, NODE_PARENTID, NODE_ISFOLDER, NODE_NAME FROM GET_TREE (:NODE_ID) INTO :NODE_ID, :NODE_PARENTID, :NODE_ISFOLDER,:NODE_NAME DO
          SUSPEND;
      ELSE
        SUSPEND;
  END
   /* Конец процедуры */ 
END
...
Рейтинг: 0 / 0
Interbase VS Firebird Heeeeeelp!
    #32231283
Фотография Dnico
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
P.S!

Соответственно 0 в параметрах - все дерево, если ХХХ, то поддерево.

ISFOLDER[ISF] = 1 /* Папка */

ISFOLDER[ISF] = 2 /* файл */
...
Рейтинг: 0 / 0
Interbase VS Firebird Heeeeeelp!
    #32231315
Фотография Zmeishe
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Похоже, но у меня не так.
1. Поскольку верхнее звено ID = 0 и ID_PARENT = 0, то твой вариант будет херачить без остановки в силу рекурсии, когда входной параметр будет 0.
2. У меня вместо NODE_ISFOLDER используется KID_COUNT.
KID_COUNT = 0 файл, KID_COUNT > 0 папка. Но это не принципиально

3. Мне непонятна конструкция.

SUSPEND;
IF (:NODE_ISFOLDER = 1) THEN
FOR рекурсия get_tree SUSPEND;
ELSE
SUSPEND;

Т.е. если файл, то два раза suspend. Или я чего-то подзабыл?
...
Рейтинг: 0 / 0
Interbase VS Firebird Heeeeeelp!
    #32231326
ZAI
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
ZAI
Гость
второй суспенд лишний стопудов
...
Рейтинг: 0 / 0
Interbase VS Firebird Heeeeeelp!
    #32231336
ZAI
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
ZAI
Гость
а в верхнем звене дерева должно быть:
Код: plaintext
1.
ParentID=null
ID= 0 
...
Рейтинг: 0 / 0
Interbase VS Firebird Heeeeeelp!
    #32231346
Фотография Dnico
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
АГА. Согласен, пропустил ... у меня там была своя обработка.

По поводу верхнего звена - тоже !

Данный вариант работает с несколькими верхними звеньями, т.е.

ID PARENTID
1 0
2 0
3 0
...
Рейтинг: 0 / 0
Interbase VS Firebird Heeeeeelp!
    #32231359
Фотография Zmeishe
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ZAI
> ParentID=null
> ID=0
Этот вариант уже обсудили, он геморройный. см. выше!
...
Рейтинг: 0 / 0
Interbase VS Firebird Heeeeeelp!
    #32231362
Фотография Dnico
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Поскольку верхнее звено ID = 0 и ID_PARENT = 0,
то твой вариант будет херачить без остановки в силу рекурсии, когда входной параметр будет 0.


Не должно вообще-то ...

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
BEGIN
  FOR SELECT ID, PID, ISF, NAME FROM GOODS
      WHERE PID = :PARENTID
      ORDER BY PID, NAME
      INTO :NODE_ID, :NODE_PARENTID, :NODE_ISFOLDER, :NODE_NAME DO BEGIN
      SUSPEND;
      IF (:NODE_ISFOLDER =  1 ) THEN
        FOR SELECT NODE_ID, NODE_PARENTID, NODE_ISFOLDER, NODE_NAME
            FROM GET_TREE (:NODE_ID)
            INTO :NODE_ID, :NODE_PARENTID, :NODE_ISFOLDER,:NODE_NAME DO
            SUSPEND;
  END
END
...
Рейтинг: 0 / 0
Interbase VS Firebird Heeeeeelp!
    #32231372
Фотография Dnico
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Zmeishe , Извиняюсь ... видимо заработался ... ID = 0 - будет цикл по верхнему звену.
Но смысла делать ID = 0 как мне кажется нет. PARENTID = 0 это и есть корень и какой у него ID вообщем-то по барабану.
...
Рейтинг: 0 / 0
Interbase VS Firebird Heeeeeelp!
    #32231382
ZAI
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
ZAI
Гость
херачить будет - будет.
4Змеище
А чтобы не херачил, надо именно так
Код: plaintext
1.
2.
3.
4.
name   id    pid
root      0      null
razd1     1       0 
razd2     2       0 
razd11    3       1 
...
Рейтинг: 0 / 0
Interbase VS Firebird Heeeeeelp!
    #32231390
Фотография Zmeishe
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dnico
> Не должно вообще-то ...

Давай рассуждать логически по шагам.
Параметр = 0
первый for select вытащит все PID равные 0, в том числе и тот который ID = 0.
присвоит :node_id в 0.
поскольку САМОЕ верхнее звено это папка, то далее рекурсия с :node_id = 0.
И понеслась 'душа в рай'.

Но это частный случай. Если у тебя нет такого звена ID=ID_PARENT=0, то циклить до бесконечности естественно не будет.

Я это звено делаю для того, чтобы
1. Избавиться от NULL
2. Создать внешний ключ для контроля целостности данных самим IB.
3. Это звено служебное. Его даже можно не показывать юзеру в программе.

Все остальные ветви юзеру только кажуться САМЫМИ верхними.
...
Рейтинг: 0 / 0
Interbase VS Firebird Heeeeeelp!
    #32231422
Gallagher
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Zmeishe, ты не прав!
Чел согласился, что корнем должен быть ID=0 PID= null
Тогда при вызове процы с параметром 0 вытаскиваются все записи, лежащие в корне (сам корень не вытащится т.к. у него ещё раз повторяю, PID=null <> 0)
потом рекурсия. Всё путём, Dnico.
Змеище тоже молодец за идею с рутом.

Gallagher
...
Рейтинг: 0 / 0
Interbase VS Firebird Heeeeeelp!
    #32231445
Фотография Zmeishe
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Я решил эту задачу в общем виде. И мне необходимо вытаскивать и вершину и всё остальное.

Поскольку ID_PARENT участвует в WHERE, то для быстродействия нужен индекс. Если там будет NULL, то для индекса это ДЫРРРКА, что не есть хорошо. К тому же ссылочную целостность в дереве контролировать надо. Мне надо, а вы как хотите.

Чтобы это не делать руками, я избавился от NULL и построил внешний ключ.
В нём и индекс и ссылочная целостность. Один единственный нолик избавил меня от кучи лишних телодвижений.
...
Рейтинг: 0 / 0
Interbase VS Firebird Heeeeeelp!
    #32231467
Фотография Dnico
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Так! Предлагаю самое простое решение:

Вершина
ID PARENTID
1 0

Ветви:
ID PARENTID
2 1
3 1
4 1
5 2
6 2


и т.д.

GET_TREE будет прекрасно работать с любым номерм PARENTID.
+ Zmeishe
Я это звено делаю для того, чтобы
1. Избавиться от NULL
2. Создать внешний ключ для контроля целостности данных самим IB.
3. Это звено служебное. Его даже можно не показывать юзеру в программе.
...
Рейтинг: 0 / 0
Interbase VS Firebird Heeeeeelp!
    #32231471
ZAI
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
ZAI
Гость
Поправим Gallaher'a
Ну ладно.
Если хочешь, чтобы был FK , тогда
первая запись в таблице ID=0 PID=0 name='root'
следующая запись ID=1 PID=0 name='root'
ID=2 PID=1 name='dir1'
ID=3 PID=1 name='dir2'
............................
Выполняй процедуру get_tree c параметром 1
Код: plaintext
get_tree( 1 )

Вытащатся все с PID>=1
...
Рейтинг: 0 / 0
Interbase VS Firebird Heeeeeelp!
    #32231485
Фотография Zmeishe
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Всё гораздо проще.
Я эту процедуру вызываю не с одним параметром, а с двумя.
Первый это ID или ID_PARENT кому, что нравиться, а вот воторой это флажок.

При самом первом вызове процедуры флажок = 0, при рекусии 1
Если процедуру Dnico дополнить
if(:flag = 0) then тогда получится моя процедура. Но не ломайте голову в понедельник принесу полный текст. Он больше текста Dnico буквально на пару, тройку коротких строчек. Не помню я сейчас.
...
Рейтинг: 0 / 0
Interbase VS Firebird Heeeeeelp!
    #32231504
Фотография Dnico
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Кстати, есть еще одна задачка не тему Tree .

Требуется процедура, которая выдает сумму по некоему полю на всех уровнях дерева.

Есть ли какие соображения? Я вот задумался, как сделать эффективнее.
...
Рейтинг: 0 / 0
Interbase VS Firebird Heeeeeelp!
    #32231565
Фотография Zmeishe
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Есть! И работает не один год. Причём считанные секунды по всему дереву сверху до низу.
Но дарить или продавать - я ещё не решил!
Я мерзкий и противный.
...
Рейтинг: 0 / 0
Interbase VS Firebird Heeeeeelp!
    #32232439
Фотография Zmeishe
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Таблица
ID ID_PARENT
0 0 // То без чего FK весьма проблематично построить, чтобы работал быстро. С Null тормоза жуткие!
1 0
2 0
3 1
4 1
и т.д.

Итак единственное принципиальное отличие от процедуры Dnico это WHERE (D.ID <> D.ID_PARENT) AND

Код: 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.
CREATE PROCEDURE GET_TREE (
    IN_PARENT INTEGER,
    FLAG INTEGER)
RETURNS (
    ID INTEGER,
    ID_PARENT INTEGER,
    NAME VARCHAR( 63 ),
    KID_COUNT INTEGER)
AS
DECLARE VARIABLE ID_TMP INTEGER;
BEGIN
  IF(:FLAG =  0 ) THEN BEGIN
       SELECT D.ID, D.ID_PARENT, D.NAME, D.KID_COUNT
       FROM DICTIONARY D
       WHERE (D.ID = :IN_PARENT)
       INTO :ID, :ID_PARENT, :NAME, KID_COUNT;
       SUSPEND;
   END

  FOR SELECT D.ID, D.ID_PARENT, D.NAME, D.KID_COUNT
        FROM DICTIONARY D
        WHERE (D.ID <> D.ID_PARENT) AND (D.ID_PARENT = :IN_PARENT)
        INTO :ID_TMP, :ID_PARENT, :NAME, :KID_COUNT
         DO BEGIN
           ID = :ID_TMP; 
           SUSPEND;
              FOR  SELECT G.ID, G.ID_PARENT, G.NAME, G.KID_COUNT
                     FROM GET_TREE (:ID_TMP,  1 ) G
                     INTO :ID, :ID_PARENT, :NAME, :KID_COUNT
                       DO
                         SUSPEND;
              END
END


Смысл FLAG следующий:
В моей задаче иногда необходимо вытаскивать одим набором данных не только потомков, но и самого родителя.
Если get_tree( 1, 0 ) то результат
1 0 // Родитель
3 1 // Потомок 1
4 1 // Потомок 1

Если get_tree( 1, 1 ) то результат
3 1 // Потомок 1
4 1 // Потомок 1

Если get_tree( 0, 0 ) то результат
0 0 // Родитель
1 0 // Потомок 0
2 0 // Потомок 0
3 1 // Потомок 1
4 1 // Потомок 1

Если get_tree( 0, 1 ) то результат
1 0 // Потомок 0
2 0 // Потомок 0
3 1 // Потомок 1
4 1 // Потомок 1
...
Рейтинг: 0 / 0
Interbase VS Firebird Heeeeeelp!
    #32232441
Фотография Dnico
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Zmeishe , Да, по поводу вытаскивания и родителя и потомков, это тоже хорошо, иногда требуется.
...
Рейтинг: 0 / 0
Interbase VS Firebird Heeeeeelp!
    #32232591
Gallagher
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
В своё оправдание хотел только напомнить, что мне нужно было вытаскивать упорядоченное по полю order дерево, причём папки по своему order 'у а файлы по своему. Этим и обуславливалась громоздкость.
...
Рейтинг: 0 / 0
Interbase VS Firebird Heeeeeelp!
    #32232647
StarWind
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Сорри конечно что опаздал... но могу сказать, что для корневого узла parent=null так же прекрасно работает....
равно как и работает условие where D.SubId = :RootId
где RootId=null

только что специально смотрел процу...
...
Рейтинг: 0 / 0
39 сообщений из 39, показаны все 2 страниц
Форумы / Firebird, InterBase [игнор отключен] [закрыт для гостей] / Interbase VS Firebird Heeeeeelp!
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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