Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > MySQL > Несколько строк при выполнении хранимой процедуры


Автор: MacTep 31.1.2008, 16:11
Есть процедура: простая, для теста, чтобы понять, как это работает.

Код

DELIMITER $$

DROP PROCEDURE IF EXISTS `aliance21`.`curdemo`$$

CREATE PROCEDURE `curdemo`(out fam varchar(30))
BEGIN
  declare done int;
  declare cur1 cursor for SELECT p_fam FROM persons;
  declare cur2 cursor for SELECT count(*) FROM persons;

  OPEN cur1;
  open cur2;

  fetch cur2 into done;

  while done > 0 do
    FETCH cur1 INTO fam;
    set done = done-1;
  end while;
  
  CLOSE cur1;
  close cur2;
END$$

DELIMITER ;
Вызываю так:
Код

call curdemo(@fam);

select @fam;
Работает хорошо, но неверно. Точнее может и верно, но надо другое. Она мне выдает последнюю строку в таблице persons. А мне надо все строки из этой таблицы. Не спрашивайте, на фига тут использовать процедуру. Понимаю, что именно в этом примере - беспонтово, можно просто отделаться запросом обычным. Но... Хотелось бы научиться выводить в хранимой процедуре именно несколько строк результирующего набора данных, а не только одну. Что делаю не так?

Автор: MacTep 1.2.2008, 08:15
Неужели это невозможно?

Автор: MacTep 4.2.2008, 07:51
Значит все-таки никак? smile

Автор: skyboy 4.2.2008, 11:04
Цитата(MacTep @  31.1.2008,  15:11 Найти цитируемый пост)
А мне надо все строки из этой таблицы

у тебя переменная объявлена так:
Цитата(MacTep @  31.1.2008,  15:11 Найти цитируемый пост)
out fam varchar(30)

одна строка длиной 30 символов. что уж тут удивительного, что процедура возвращает в этой переменной одну строку?
вот, если бы у тебя был бы объявлен тип "таблица" - вернул бы несколько строк. Но в MySQL такого типа данных пока нет.
Так что при данной постановке вопроса - никак.

Автор: MacTep 5.2.2008, 07:59
Цитата

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

Автор: skyboy 5.2.2008, 10:37
используя сериализацию в виде агрегирующей функции http://dev.mysql.com/doc/refman/4.1/en/group-by-functions.html#function_group-concat, можно слить кучу записей в одну строку с разделителями(аналог функции http://php.net/implode), но есть ньюансы: 
- используемое в качестве разделителя не может встречаться в "соединяемых" значениях - потом не отделишь одно от другого
- есть ограничение на максимальную длину подобной строки: group_concat_max_len; это ограничение можно изменить, но если пользователь имеет права на изменения переменных сервера
- необходимо парсить
---------------------------
используя динамический SQL с созданием представления(view) с проивзольным генерируемым именем, которое ты и будешь возвращать, а после обработки - прибивать. если имя представления будет достаточно уникальным(всякие там GUID() для генерации приветствуются), то коллизий не будет.
Но я не уверен, что такой подход реально реализовать: это только идея. динамический SQL точно не работает в функциях(даже если оно используется не напрямую, а из процедуры, вызываемой из функции). может и  в процедурах быть какие-то ограничения. я не в курсе :(
---------------------------
в любом случае, на твоем месте я бы попытался поставить задачу так, чтоб для её решения не использовались приёмы, нетипичные для работы с реляционными СУБД(всякие там динамические SQL и сериализация с парсингом  - это костыли)

Автор: MacTep 5.2.2008, 16:37
Цитата

на твоем месте я бы попытался поставить задачу так, чтоб для её решения не использовались приёмы, нетипичные для работы с реляционными СУБД
Ну вообще, данная задача вполне типична для реляционной БД. Зря ты так. Например, скажем, FireBird на ура выполняет такое. Просто тут дело именно в MySQL и использовать надо только его. В общем, я понял, задачу буду сводить к другому решению. Благо, обойти можно.

Автор: skyboy 5.2.2008, 17:03
MacTep, в смыле? не знаю, как для FireBird, а в MSSQL имеется тип данных TABLE. Вот при помощи такого "структурного" типа данных и можно возвращать несколько записей. А вот динамически создавать View, или объединять на стороне СУБД записи в одну строку, а потом на стороне клиента парсить - вот ЭТО считаю не лучшим применением РСУБД.
я ж так и написал:
Цитата(skyboy @  5.2.2008,  09:37 Найти цитируемый пост)
всякие там динамические SQL и сериализация с парсингом  - это костыли

что, неужели под FireBird повсеместно используется "склейка" в строку с последующим парсингом?!

Автор: MacTep 6.2.2008, 07:52
Цитата(skyboy @  5.2.2008,  17:03 Найти цитируемый пост)
А вот динамически создавать View, или объединять на стороне СУБД записи в одну строку, а потом на стороне клиента парсить - вот ЭТО считаю не лучшим применением РСУБД.
А я и не собираюсь это применять. ;) А в firebird просто можно при помощи suspend возвращать то, что надо в хранимой процедуре.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)