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


Автор: Oleg 19.11.2002, 19:11
Привет всем!
Вот если есть у меня хранимая процедура в Oracle8i БД,  
например просто SELECT * FROm something... Как мне датасет отобразить в
делфячьей форме (не говорю в DBGrid)? В параметрах хр.проц. можно вернуть
тип данных ftCursor, в хелпе сказано, что возвращает курсор из Oracle.
Если это ключ, то как им пользоваться? Спасибо.

Автор: AntonSaburov 21.11.2002, 22:11
Так никто и не ответил. Жаль. Очень хотелось бы знать. У меня было некое промежуточное решение с использованием временных таблиц. Процедура туда записывает, Следующий оператор - читает.
Но хотелось, чтобы как в MS SQL. Похоже не получится :(

Автор: Medved 22.11.2002, 05:55
Код

Так никто и не ответил. Жаль. Очень хотелось бы знать.


Ладно поспешу опередить события и отвечу....

Да, дело в том, что если мы напишем в хранимой процедуре (и не только в ней. здесь имеется в виду, без каких либо компонент, т.е. напрямую) просто запрос SELECT * FROM MyTable то Oracle не воспримет такую конструкцию.... вернее он возвратит результат, но мы с ним ничего не сможем сделать..... это будет не набор данных (как мы это привыкли понимать, а такая "картинка") мы не сможем ни осуществлять навигацию по ней, ничего с ней сделать.... Oracle не позволяет (скорее всего по соображениям безопасности) осуществлять прямой доступ к таблицам.

Чтобы получить такой набор данных (в смысле "живой" с которым можно манипулировать, т.е. осуществлять навигацию и тд.), мы должны результаты какого-либо запроса, присвоить курсору (есть еще и другие подобные конструкции PL/SQL, такие как "записи" и "таблицы", но о них в другой раз)
Курсор - означает "текущий набор записей" и представляет из себя специальный элемент PL/SQL, с которым связан SQL-оператор SELECT.
Но отойдем от теории и рассмотрим пример:
У нас таблицы студентов (students), в которой четыре поля
0) ID;
1) Имя (Name);
2) Фамилия (Surname);
3) Курс (Kurs).

Код

DECLARE
/* Обьявляем выходные переменные для хранения результатов запроса */
 v_studentID     students.ID%TYPE;
 v_Name          students.Name%TYPE;
 v_SurName       students.Surname%TYPE;

/* Переменная привязки, используемая в запросе */
 v_kurs          stusents.Kurs%TYPE := 2;

/* Создаем курсор */
CURSOR c_students IS
 SELECT  ID, Name,  SurName
      FROM students
      WHERE  kurs = v_kurs;

BEGIN
/* Открываем курсор */
 OPEN c_students;

/* Начинаем цикл пробежки по записям */
 LOOP
 /* Сейчас выбирем каждую строку курсора (активного набора данных) в определенные нами переменные */
 FETCH c_students INTO v_studentID, v_Name, v_SurName;
/* Если строки, которые нужно выбрать закончились,  выйдем из цикла */
 EXIT WHEN c_students%NOTFOUND;
END LOOP;

/* Закроем курсор */
CLOSE c_students;
END;


Здесь хотелось бы обратить ваше внимание на конструкции PL/SQL которые я использовал:

1) CURSOR <имя курсора> IS <запрос SELECT>. - создание курсора;
2) OPEN <имя курсора> - открытие курсора;
3) LOOP
   <операторы;>
   EXIT WHEN <условие выхода>;
  END LOOP;
Это конструкция цикицеской обработки (читай - "цикл");
4) FETCH <имя курсора> INTO <список переменных куда заносяться результаты выборки>;
5) CLOSE <имя курсора>; - закрытие курсора;

Вот вообщем-то и все! Хотя это лишь сотая часть из того, что относиться к курсорам и вообще выборки записей из таблиц Oracle...

Но как я уже сказал... скоро будет цикл статей по этому поводу. Кому интересно, ждите....

P.S. Да, еще важно в конструкции - FETCH <имя курсора> INTO <список переменных куда заносяться результаты выборки>, чтобы количество переменных, в которые мы заносим результаты выборки из курсора, соответствовали типу и количеству полей, которые мы указываем после оператора SELECT, когда мы создаем курсор;

Автор: AntonSaburov 22.11.2002, 21:45
Г-н Pegas !
Был задан КОНКРЕТНЫЙ вопрос, а вы стали разводить непонятную теорию. Тот код, который приведен, то, что просилось изначально - НЕ ДЕЛАЕТ.
Нафига флейм разводить ? Показать свою осведомленность ?
Ну так заводите отдельную тему с циклом статей. А показательные примеры на уровне документации "для чайников" не надо !

Прошу рассматривать сие послание не как наезд или обвинение в профнепригодности, но хотелось услышать ответ на поставленный вопрос

МОЖНО ЛИ, И ЕСЛИ МОЖНО, ТО КАК ВЕРНУТЬ ИЗ ХРАНИМОЙ ПРОЦЕДУРЫ НА ORACLE
В ВИДЕ НАБОРА ДАННЫХ ?
Например, как в MS SQL.

Автор: Medved 23.11.2002, 02:43
Цитата

Г-н Pegas !
Был задан КОНКРЕТНЫЙ вопрос, а вы стали разводить непонятную теорию. Тот код, который приведен, то, что просилось изначально - НЕ ДЕЛАЕТ.
Нафига флейм разводить ? Показать свою осведомленность ?
Ну так заводите отдельную тему с циклом статей. А показательные примеры на уровне документации "для чайников" не надо !

Прошу рассматривать сие послание не как наезд или обвинение в профнепригодности, но хотелось услышать ответ на поставленный вопрос

МОЖНО ЛИ, И ЕСЛИ МОЖНО, ТО КАК ВЕРНУТЬ ИЗ ХРАНИМОЙ ПРОЦЕДУРЫ НА ORACLE
В ВИДЕ НАБОРА ДАННЫХ ?
Например, как в MS SQL.


Фу, какая невоспитанность....... на такой вопрос даже отвечать нехочется.....

Автор: AntonSaburov 23.11.2002, 03:05
Цитата(Pegas @ 22.11.2002, 18:43)
Цитата

МОЖНО ЛИ, И ЕСЛИ МОЖНО, ТО КАК ВЕРНУТЬ ИЗ ХРАНИМОЙ ПРОЦЕДУРЫ НА ORACLE
В ВИДЕ НАБОРА ДАННЫХ ?
Например, как в MS SQL.


Фу, какая невоспитанность....... на такой вопрос даже отвечать нехочется.....

Я действительно несколько вспылил. За что извиняюсь.
Но просто очень хотелось услышать ответ, который у меня изредка всплывает уже в течении нескольких лет. А воз и ныне там.

Автор: Medved 25.11.2002, 06:42
Да, не все так просто, как мне показалось, должен извиниться, надо работать не через курсор, а объявлять в качестве выходного параметра записи (имя_записи имя_таблицы%ROWTYPE), и используй в качестве компонентов для доступа к Oracle - библиотеку ODAC, я о ней раньше писал.... там есть такаой компонент OraStoredProc....

Автор: AntonSaburov 25.11.2002, 21:21
Цитата(Pegas @ 24.11.2002, 22:42)
Да, не все так просто, как мне показалось, должен извиниться, надо работать не через курсор, а объявлять в качестве выходного параметра записи (имя_записи имя_таблицы%ROWTYPE), и используй в качестве компонентов для доступа к Oracle - библиотеку ODAC, я о ней раньше писал.... там есть такаой компонент OraStoredProc....

А вот за эту идею - спасибо. Надо посмотреть. Мне тут знакомые тоже что-то такое посоветовали.

Автор: Oleg 26.11.2002, 03:36
Yes, people, we got it! :laugh  :laugh  :laugh
Читайте ЭТО!

create or replace table periods(  -- создадим тестовую таблицу
 pid  varchar2(10),
 name varchar2(3));
/

insert into periods(pid, name) values('1','JAN');
insert into periods(pid, name) values('2','FEB');
insert into periods(pid, name) values('3','MAR');
insert into periods(pid, name) values('4','APR');
insert into periods(pid, name) values('5','MAY');
insert into periods(pid, name) values('6','JUN');
insert into periods(pid, name) values('7','JUL');
insert into periods(pid, name) values('8','AUG');
insert into periods(pid, name) values('9','SEP');
insert into periods(pid, name) values('10','OCT');
insert into periods(pid, name) values('11','NOV');
insert into periods(pid, name) values('12','DEC');
/
create or replace type tRec as object(  -- создадим обьектный тип для
 pid  varchar2(10),                    -- записи
 name varchar2(3));
/

create or replace type tTab as table of tRec;
/ -- создаем таблицу записей

create or replace function f_Periods  -- сама хранимая функция
return tTab as
p varchar2(10);
n varchar2(3);
res tTab:= tTab() ;
rec tRec:= tRec(p,n) ; -- инициализация составного типа
a Number;
cnt Number;
begin
 select count(*) into cnt from periods;
 for a in 1..cnt LOOP
   Res.extend;
  select pid, name into rec.pid, rec.name
  from periods
  where
    pid = a;
    res(a):= rec;
 END LOOP;
 RETURN Res;
end;
/

-- а вот и сам текст кверя
-- ОБРАТИТЕ ВНИМАНИЕ: cast

select * from table(cast(f_periods() as tTab));

Победа!  :colgate

P.S. Кстати, вопрос к  Pegas'у: я-то ODAC скачал, но я так понял,
что он триальный со всеми вытекающими...Что с ним сделать или
зачем он нужен тогда? Штука, согласен, неплохая.

Автор: Medved 28.11.2002, 06:45
Молодчинка!

P/S/ а по поводу ODAC я даже точно не знаю...... его мой коллега скачивал, но у меня он не триальный. Я завтра у него спрошу, что он там с ним вытворял  :colgate  и точно уже отвечу.... если что, через неделю я его на своем сайте выложу (пока кроме фото там ничего нет, можно не смотреть)....

Автор: Medved 29.11.2002, 05:59
Разузнал! Компоненты для прямого доступа к Oracle из Дельфи - ODAC и DAO находятся на сайте http://oraclebones.narod.ru

Там же лежит и SQL Developer - удобная штука между прочим!

З.Ы. все компоненты рабочии, не триальные...

Автор: Oleg 28.12.2002, 18:22
Спасибо, Pegas! :thumbs-up  Теперь подождем, когда oraclebones выложит
ODAC под Delphi7.

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