Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Firebird, InterBase [игнор отключен] [закрыт для гостей] / Interbase VS Firebird Heeeeeelp! / 25 сообщений из 39, страница 1 из 2
08.08.2003, 11:42
    #32230886
Gallagher
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Interbase VS Firebird Heeeeeelp!
Народ, сидевший за 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
08.08.2003, 11:49
    #32230914
alex_k
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Interbase VS Firebird Heeeeeelp!
давай свой ХП и свой параметр... заодно дельфевый код давай, как данные их хп читаешь....
...
Рейтинг: 0 / 0
08.08.2003, 11:52
    #32230927
Dnico
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Interbase VS Firebird Heeeeeelp!
И какое сообщение вылетает ?
А то уж совсем не понятно что происходит ...
...
Рейтинг: 0 / 0
08.08.2003, 11:58
    #32230937
Zmeishe
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Interbase VS Firebird Heeeeeelp!
Чтобы вызвать из Дельфей, по моему нужно двоеточие, для начала!
select * from Proc_Name( : Param)
...
Рейтинг: 0 / 0
08.08.2003, 12:00
    #32230942
Gallagher
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Interbase VS Firebird Heeeeeelp!
Тока не пугайтесь !)
Это всё надо для организации упорядоченного дерева в одной таблице 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
08.08.2003, 12:06
    #32230960
Zmeishe
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Interbase VS Firebird Heeeeeelp!
Ну так если ты прередаёшь NULL, то вытаскивай не (node_parent_id = :PARENT_ID), а (node_parent_id is null ).

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

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

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

Проца 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
08.08.2003, 13:19
    #32231092
alex_k
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Interbase VS Firebird Heeeeeelp!
избавься от порочной практики использования NULL
замени на 0 везде, и поле объяви not null (но не наоборот, а то огребешься)
...
Рейтинг: 0 / 0
08.08.2003, 13:29
    #32231104
Zmeishe
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Interbase VS Firebird Heeeeeelp!
Не только короче, но и по скорости быстрее будет так:
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
08.08.2003, 13:54
    #32231151
Gallagher
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Interbase VS Firebird Heeeeeelp!
Спасиба огромное, друзья, но из всего приму тока создать корень с ID=PARENT_ID=0, ибо Fk уже висит, а вводить поле количество детей - грозит громадными тормозами триггеров при перемещении ветвей друг в друга (а у меня их с полторы тысячи)
...
Рейтинг: 0 / 0
08.08.2003, 14:08
    #32231180
Dnico
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Interbase VS Firebird Heeeeeelp!
Смотрю я на текст ХП и диву даюсь ... А слабо GET_TREE в 6 строках ?
...
Рейтинг: 0 / 0
08.08.2003, 14:24
    #32231211
Gallagher
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Interbase VS Firebird Heeeeeelp!
Да есть тут с десяток идей....
...
Рейтинг: 0 / 0
08.08.2003, 14:32
    #32231233
Gallagher
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Interbase VS Firebird Heeeeeelp!
В скорости ты уж точно не выиграешь... вроде бы :(
...
Рейтинг: 0 / 0
08.08.2003, 14:34
    #32231239
Zmeishe
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Interbase VS Firebird Heeeeeelp!
Gallagher
> грозит громадными тормозами триггеров при перемещении ветвей друг в друга (а у меня их с полторы тысячи)

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

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

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

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

Код: 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
08.08.2003, 14:53
    #32231283
Dnico
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Interbase VS Firebird Heeeeeelp!
P.S!

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

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

ISFOLDER[ISF] = 2 /* файл */
...
Рейтинг: 0 / 0
08.08.2003, 15:08
    #32231315
Zmeishe
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Interbase VS Firebird Heeeeeelp!
Похоже, но у меня не так.
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
08.08.2003, 15:17
    #32231326
ZAI
ZAI
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Interbase VS Firebird Heeeeeelp!
второй суспенд лишний стопудов
...
Рейтинг: 0 / 0
08.08.2003, 15:22
    #32231336
ZAI
ZAI
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Interbase VS Firebird Heeeeeelp!
а в верхнем звене дерева должно быть:
Код: plaintext
1.
ParentID=null
ID= 0 
...
Рейтинг: 0 / 0
08.08.2003, 15:27
    #32231346
Dnico
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Interbase VS Firebird Heeeeeelp!
АГА. Согласен, пропустил ... у меня там была своя обработка.

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

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

ID PARENTID
1 0
2 0
3 0
...
Рейтинг: 0 / 0
08.08.2003, 15:33
    #32231359
Zmeishe
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Interbase VS Firebird Heeeeeelp!
ZAI
> ParentID=null
> ID=0
Этот вариант уже обсудили, он геморройный. см. выше!
...
Рейтинг: 0 / 0
08.08.2003, 15:35
    #32231362
Dnico
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Interbase VS Firebird Heeeeeelp!
Поскольку верхнее звено 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
Форумы / Firebird, InterBase [игнор отключен] [закрыт для гостей] / Interbase VS Firebird Heeeeeelp! / 25 сообщений из 39, страница 1 из 2
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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