Страница 1 из 1

Firebird, хранимые процедуры и хлебные крошки

СообщениеДобавлено: 09.12.2017 20:27:55
wofs
Доброго дня!
Имеем таблицу вида:
Код: Выделить всё
ID                IDPARENT                NAME

В ней хранится некое классическое дерево.
Стоит задача получить "Хлебные Крошки" (Навигационную цепочку) от указанного узла до корня.
Чтение документации привело меня к написанию такой хранимой процедуры:
Код: Выделить всё
create or alter procedure GETPARENTS_GROUP_CATALOG (
    ID integer)
returns (
    CID integer,
    PARENTID integer,
    NAME varchar(30))
as
declare variable VARBREADCRUMPS varchar(6000);
BEGIN
    varbreadcrumps = '';
  WHILE (:ID > 0) DO /* ищем до корня */
    BEGIN
      SELECT G.ID, G.IDPARENT, G.NAME
      FROM "GROUP-CATALOG" G
      WHERE G.ID = :ID
      INTO :CID, :PARENTID, :NAME;
      varbreadcrumps = NAME||'  '||varbreadcrumps;
      ID = :PARENTID; /* код родителя для следующей выборки */
      SUSPEND;
    END
END

Так как процедура селективная, то вызываю строкой:
Код: Выделить всё
select * from GETPARENTS_GROUP_CATALOG(10);

К моменту достижения корня дерева переменная varbreadcrumps содержит полный путь от указанного узла до корня.
Теперь стоит задача "свернуть" результат работы процедуры и вывести его(результат) одной строкой, содержащую только переменную varbreadcrumps.
Код: Выделить всё
select * from GETPARENTS_GROUP_CATALOG(IDNode3); =>> [Root  Node1  Node2  Node3]

В этом у меня проблема... Прошу помощи...

Добавлено спустя 8 минут 29 секунд:

Разобрался.
Надо перенести
Код: Выделить всё
SUSPEND;

И процедура примет вид:
Код: Выделить всё
create or alter procedure GETPARENTS_GROUP_CATALOG (
    ID integer)
returns (
    BREADCRUMPS varchar(6000),
    CID integer,
    PARENTID integer,
    NAME varchar(30))
as
declare variable VARBREADCRUMPS varchar(6000);
BEGIN
    varbreadcrumps = '';
  WHILE (:ID > 0) DO /* ищем до корня */
    BEGIN
      SELECT G.ID, G.IDPARENT, G.NAME
      FROM "GROUP-CATALOG" G
      WHERE G.ID = :ID
      INTO :CID, :PARENTID, :NAME;
      varbreadcrumps = NAME||' \ '||varbreadcrumps;
      breadcrumps = varbreadcrumps;
      ID = :PARENTID; /* код родителя для следующей выборки */
      --SUSPEND;
    END
    SUSPEND;
END

Re: Firebird, хранимые процедуры и хлебные крошки

СообщениеДобавлено: 11.12.2017 10:41:07
alexs
Такие вещи можно делать рекурсивными запросами

Код: Выделить всё
CREATE TABLE TEST_1(
  TEST_1_ID INTEGER NOT NULL,
  TEST_1_OWN_ID INTEGER,
  TEST_1_NAME VARCHAR(150),
  PRIMARY KEY (TEST_1_ID)
);
   
with recursive aa (TEST_1_ID, TEST_1_OWN_ID, TEST_1_NAME)
as
  (
   select
     test_1.TEST_1_ID,
     test_1.TEST_1_OWN_ID,
     test_1.TEST_1_NAME
   from
     test_1
   where
     test_1.TEST_1_ID = 4

   union all

   select
     test_1.TEST_1_ID,
     test_1.TEST_1_OWN_ID,
     test_1.TEST_1_NAME || '\'|| aa. TEST_1_NAME
   from
     test_1
     inner join aa on test_1.TEST_1_ID = aa.TEST_1_OWN_ID
  )
select
  *
from
  aa
where
  aa.TEST_1_ID = 1


В запросе:
1 - это корневой узел
4 - это лист, от которого строим маршрут

Re: Firebird, хранимые процедуры и хлебные крошки

СообщениеДобавлено: 11.12.2017 20:14:38
wofs
alexs писал(а):Такие вещи можно делать рекурсивными запросами

Хм... спасибо, не знал о такой возможности.