Формирование и возврат многострочного результата с хранимой процедуры

DigitalBrain
Дата: 01.01.2013 22:50:15
Здравствуйте!
Я только начал разбираться с хранимыми процедурами в мускуле, гугл не помог, по этому не пинайте сильно =)
проблема - не могу с процедуры получить много строчный результат сформированный вручную, а не с выборки таблицы...
по логике надо как то описать результирующую таблицу...но есть ли такое хз)
задача такая: есть таблица для описания древовидной структуры т.е у каждой записи есть поле Parent что ссылается на id-ключ записи родителя...ну и надо вывести всех "родителей" этой записи..т.е такое:
ID NAME PARENT
1 Music 3
3 Media 8
8 Main 0
ну а выводит только одну строку...т.е следующие Select игнорируются и результат однострочный..


Написал что то такое:
CREATE DEFINER = 'root'@'localhost'
PROCEDURE music.GetDirParents(DIR        BIGINT,
                              DIRS_COUNT SMALLINT
                              )
BEGIN
  DECLARE N INT DEFAULT DIRS_COUNT;
  DECLARE _ID, _PARENT  BIGINT;
  DECLARE _NAME         VARCHAR(64);

  WHILE N > 0
  DO
   SET N = N - 1;
   SELECT `ID`,`NAME`,`PARENT` INTO _ID,_NAME,_PARENT from `DIRS` WHERE `ID`=DIR LIMIT 1;
   SET DIR = _PARENT;
   SELECT _ID, _NAME, _PARENT;
  END WHILE;
END


Спасибо=)
miksoft
Дата: 01.01.2013 23:14:41
А чем вы читаете результат из MySQL? Какая библиотека, компоненты доступа и т.п. ?
DigitalBrain
Дата: 01.01.2013 23:24:01
miksoft
А чем вы читаете результат из MySQL? Какая библиотека, компоненты доступа и т.п. ?

Клиент - PHP5 библиотека [Client API version mysqlnd 5.0.7-dev - 091210 - $Revision: 304625 $]
Но судя по всему не в ней дело ибо если сделать в процедуре Select с многострочным результатом напрямую без переменных то php тоже получает все строки...
miksoft
Дата: 01.01.2013 23:29:15
DigitalBrain
Клиент - PHP5 библиотека
Которая из них? Если мне память не изменяет, то их четыре разных штуки.
Вам нужна та из них, которая умеет получать результат мультиселекта.
Про оригинальный API можете прочитать здесь - C API Support for Multiple Statement Execution.
Про соответствующие фичи используемой библиотеки читайте в доке по ней же.
trew
Дата: 01.01.2013 23:51:46
DigitalBrain,

Немного измените код процедуры:
Создайте временную таблицу, и в цикле закидывайте туда данные.
В конце процедуры, вывод данных из временной таблицы. Код для MySQL в средине статьи
DigitalBrain
Дата: 02.01.2013 00:09:27
trew,
Гм...да вот смущает что ради казалось бы простейшей операции нужно создавать временные таблицы...тут вопрос с рациональностью из за производительности...Сомневаюсь что народ ради многострочного результата такие костыли юзает...хотя могу ошибаться )
Если бы поля были разные у Selectов то это я еще понимаю почему оно только первый выводит....
откопал сомнительный код в гугле с одной статьи , но мистического оператора "RESULT" в мускуле нет...
как то все странно...

//Процедура, формирующую результирующе множество
CREATE PROCEDURE Get_list_absent
/* Процедура определяет перечень книг, 
находящиеся на руках у читателя, имеющего
читательскую карточку с номером par_N_reader */
(
IN Par_N_reader SMALLINT 
)
[b]RESULT[/b] (    Fld_Author LONG VARCHAR, 
        Fld_Title_book LONG VARCHAR, 
        Fld_City_publish CHAR(15), 
        Fld_Publisher CHAR(20), 
        Fld_Year_publish SMALLINT)
BEGIN
/* В операторе SELECT введены псевдонимы B и
A для  таблиц Stepanov.Books и Stepanov.Absent, 
соответственно */
SELECT B.Author, B.Title_book,
        B.City_publish, B.Publisher,
        B.Year_publish 
    FROM(Stepanov.Books AS B NATURAL
            JOIN Stepanov.Copies) NATURAL
            JOIN Stepanov.Absent AS A
    WHERE A.N_reader= 	Par_N_reader 
END
trew
Дата: 02.01.2013 00:27:47
DigitalBrain,

Вот получше решение
13509125
Т.е. это получиться процедура с параметром.
DigitalBrain
Дата: 02.01.2013 03:20:02
так, день явно потрачен зря) панацеи не найдено .Написал через временный тейбл , работает конечно, но нет никакого удовлетворения от такого изврата( как с базухи по воробьям ..

PROCEDURE music.GetDirParents(DIR BIGINT,DIRS_COUNT SMALLINT)
BEGIN
  DECLARE N INT DEFAULT DIRS_COUNT;
  DECLARE _ID, _PARENT  BIGINT;
  DECLARE _NAME         VARCHAR(64);
 CREATE TEMPORARY  TABLE IF NOT EXISTS `temp` (id BIGINT,NAME VARCHAR(64),PARENT BIGINT); 
  loop1:WHILE N > 0
  DO
   SET N = N - 1;
   SET _ID = 0;
   SELECT `ID`,`NAME`,`PARENT` INTO _ID,_NAME,_PARENT from `DIRS` WHERE `ID`=DIR LIMIT 1;
   if(_ID=0) THEN LEAVE loop1;END IF; 
   SET DIR = _PARENT;
   INSERT INTO TEMP VALUES(_ID, _NAME, _PARENT);
  END WHILE;
  SELECT * FROM  temp;
  DROP TEMPORARY TABLE temp;
END