Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / как вернуть рекордсет из функции? / 19 сообщений из 19, страница 1 из 1
21.07.2006, 13:37
    #33869958
Winnipuh
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
как вернуть рекордсет из функции?
Я могу вернуть RETURNS SETOF integer.

А если мне надо вернуть рекордсет из запсией типа:
integer, varchar, bit

Как ?
...
Рейтинг: 0 / 0
21.07.2006, 13:51
    #33870017
4321
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
как вернуть рекордсет из функции?
WinnipuhЯ могу вернуть RETURNS SETOF integer.

А если мне надо вернуть рекордсет из запсией типа:
integer, varchar, bit

Как ?или
CREATE TYPE my_type AS....
(см доку на CREATE TYPE)
и
...RETURNS SETOF my_type ...

или же через "псевдотип" RECORD:

...RETURNS SETOF RECORD ...
...
Рейтинг: 0 / 0
21.07.2006, 13:55
    #33870036
Winnipuh
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
как вернуть рекордсет из функции?
спасибо,
вот функция, компилируется нормально, но при выборке пишет ошибку

ERROR: a column definition list is required for functions returning "record"

----------------


CREATE OR REPLACE FUNCTION GetChildren(var_node_id uuid)
RETURNS SETOF RECORD
AS
$body$
DECLARE result RECORD;
BEGIN
create temporary
table tst( node_id uuid,
parent_id uuid,
level integer not null default 0
)
on commit drop;
-- здесь заполняется временная таблица
for result in
select node_id,parent_id,level from tst
LOOP
return NEXT result;
END LOOP;

RETURN;
END;
$body$
LANGUAGE 'plpgsql' VOLATILE CALLED ON NULL INPUT SECURITY INVOKER;
...
Рейтинг: 0 / 0
21.07.2006, 14:01
    #33870066
Winnipuh
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
как вернуть рекордсет из функции?
определил композитный тип, в принципе - нормальное, быстрое решение

(Y)
...
Рейтинг: 0 / 0
21.07.2006, 14:08
    #33870107
domanix
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
как вернуть рекордсет из функции?
вот тебе пример рекордсета вобще не связанного с данными в бд ...

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
CREATE OR REPLACE FUNCTION myrecordset
(in cnt integer,out id integer, out name text,out b bit)
RETURNS SETOF record LANGUAGE 'plpgsql'  AS
$body$
declare    x integer= 0 ;
begin
 while x<cnt loop
   id=x;    name='x^2='||x*x;    b= 1 ;
   x=x+ 1 ;return next;
 end loop;
end $body$;
Вот пример вызова
Код: plaintext
select * from myrecordset( 100 ) where id> 80 ;

Надеюсь на этом примере понятно показанно как это делается?
Или еще вопросы будут?
...
Рейтинг: 0 / 0
21.07.2006, 14:08
    #33870112
4321
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
как вернуть рекордсет из функции?
Winnipuhспасибо,
вот функция, компилируется нормально, но при выборке пишет ошибку

ERROR: a column definition list is required for functions returning "record"

SELECT для ф-ии с типом "рекорд" требует указания "листа определения колонок"
т.е. определение типа вывода переносится на этап SELECT-а .
Все см в доке, или тут - поиском (возможно - по фрагменту сообщения).
...
Рейтинг: 0 / 0
21.07.2006, 14:18
    #33870152
domanix
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
как вернуть рекордсет из функции?
то :4321
в восьмерке появились параметры in и out
и необходимость определять тип результата функции или указывать список колонок для типа record уже отпала.
так что ежели у воспрошающего pG 8 - то пусть пишет как я привел выше. Это значительно облегчает жизнь.. Ежели не 8 тады ой....
...
Рейтинг: 0 / 0
21.07.2006, 14:34
    #33870218
domanix
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
как вернуть рекордсет из функции?
Или вот так - расширим примерчик:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
CREATE OR REPLACE FUNCTION myrecordset
(in cnt integer, out id integer, out name text, out b bit)
RETURNS SETOF record LANGUAGE 'plpgsql'  AS $body$
declare    x integer= 0 ;
              r record;
begin
for r in select oid,pg_class.relname, 1  as ff from pg_class loop
 id=r.oid;
 name=r.relname;
 b=r.ff;
 return next;
end loop;

while x<cnt loop
   id=x;    name='x^2='||x*x;  b= 1 ;
   x=x+ 1 ;return next;
 end loop;
end $body$;
select * from myrecordset( 100 );
...
Рейтинг: 0 / 0
21.07.2006, 15:11
    #33870414
Winnipuh
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
как вернуть рекордсет из функции?
версия 8, так проще, спасибо.

Еще вопрос из этой же функции:

из-за того, что создаю временную таблицу не могу повторно вызвать функцию, пишет ошибку ОИД.

пришлось использовать

execute 'insert into tst(node_id,parent_id) select id,parent_id from nodes where parent_id=var_node_id;';

вопрос: здесь var_node_id - это входной параметр функции, и execute не видит его.

как быть?...
...
Рейтинг: 0 / 0
21.07.2006, 17:35
    #33871054
domanix
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
как вернуть рекордсет из функции?
Несколько вариантов
1
Собирать самому запрос полностью r примеру:
Код: plaintext
1.
2.
3.
4.
5.
EXECUTE 'UPDATE tbl SET '
        || quote_ident(colname)
        || ' = '
        || newvalue
        || ' WHERE key = '
        || quote_literal(keyvalue);

2. Отказаться от временной таблицы.
в том примере что ты привел - временная таблица - в принципе не нужна..
Можно данные сразу выдавать наружу через return next;
...
Рейтинг: 0 / 0
21.07.2006, 17:49
    #33871100
Winnipuh
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
как вернуть рекордсет из функции?
2 domanix:
увы, нужна, самое интересное за этим скрыто

-- здесь заполняется временная таблица
вот в T-SQL как сделано, я формирую список всех потомков дерева


BEGIN
declare @rows int
insert into @out(node_id,parent_id)
select [id], parent_id from dbo.nodes where parent_id=@node_id
set @rows=@@ROWCOUNT
while(@rows>0)
begin
update @out set [level]=[level]+1
insert into @out(node_id,parent_id)
select [id], parent_id from dbo.nodes
where parent_id in (select node_id from @out where [level]=1)
set @rows=@@ROWCOUNT; if(@rows=0) break;
end
...
Рейтинг: 0 / 0
21.07.2006, 17:57
    #33871127
4321
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
как вернуть рекордсет из функции?
Winnipuh2 domanix:
увы, нужна, самое интересное за этим скрыто

-- здесь заполняется временная таблица
вот в T-SQL как сделано, я формирую список всех потомков дерева
что мешает вам выводить набор потомков в качестве ф-ии (которую кстати можно джойнить как обычную таблицу), а не заполнять зачем-то времянку? Или вы хотите ее опосля проиндексировать?
...
Рейтинг: 0 / 0
21.07.2006, 18:09
    #33871179
Winnipuh
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
как вернуть рекордсет из функции?
4321 Winnipuh2 domanix:
увы, нужна, самое интересное за этим скрыто

-- здесь заполняется временная таблица
вот в T-SQL как сделано, я формирую список всех потомков дерева
что мешает вам выводить набор потомков в качестве ф-ии (которую кстати можно джойнить как обычную таблицу), а не заполнять зачем-то времянку? Или вы хотите ее опосля проиндексировать?

нет, мне нужен только список, рекордсет на выходе.
node_id, parent_id, level

Я так формировал в mssql процедуре, в цикле заполняется временная таблица и потом селект из нее.
с одной стороны врем таблица, а сдругой я использую тип uuid, который не преобразовывается ни в какой другой...


не совсем понял Вашу идею. как?...
...
Рейтинг: 0 / 0
21.07.2006, 18:11
    #33871192
Winnipuh
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
как вернуть рекордсет из функции?
в T-SQL я избавился от рекурсии. Возможно здесь рекурсивно обойти?...
...
Рейтинг: 0 / 0
21.07.2006, 18:19
    #33871229
Winnipuh
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
как вернуть рекордсет из функции?
как такое решение?
:-)

CREATE OR REPLACE FUNCTION "public"."getchildren" (var_node_id "public"."uuid", var_level integer) RETURNS SETOF "public"."parent_record" AS
$body$
DECLARE result RECORD;
DECLARE rows_conter integer;
DECLARE query text;
BEGIN
if exists(select id,parent_id,1 from nodes where parent_id=var_node_id)
then
for result in
select id,parent_id,1 from nodes where parent_id=var_node_id
LOOP
select * from GetChildren(id, level+1);
return NEXT result;
END LOOP;
end if;
RETURN;
END;
$body$
LANGUAGE 'plpgsql' VOLATILE CALLED ON NULL INPUT SECURITY INVOKER;
...
Рейтинг: 0 / 0
21.07.2006, 18:21
    #33871236
4321
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
как вернуть рекордсет из функции?
что вам мешает открывать рекордсет не по селекту к таблице, а скажем по выборке вида:
select * from myrecordset(100);

или вы хотите потом измываться над данными?

так ничто вам не мешает вызывать вашу ф-ю из другой, в которой и еще раз преобразовывать данные.

единственное место, где возможно оправдана именно темповая таблица, это когда вы собираетесь ее ну очень многократно вызывать в некой другой процедуре, а гарантировать, что вызов этой вашей ф-ии|таблицы будет произведен один раз для всех ее вхождений в вызывающую - вы не можете.

а использовать ф-ию можно примерно так:
select * from
myrecordset(100) AS r INNER JOIN my_table USING(id) ;

ах да, вспомнил. Вы еще можете захотеть менять данные темповой выборки руками (с тем, чтобы потом куда-то влить). Если это - ваш случай, то видимо да, вам будет удобно работать с темповой.
...
Рейтинг: 0 / 0
31.07.2006, 09:36
    #33888170
Vladimir Lavrentiev
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
как вернуть рекордсет из функции?
domanix
Код: plaintext
1.
2.
3.
4.
CREATE OR REPLACE FUNCTION myrecordset
(in cnt integer,out id integer, out name text,out b bit)
RETURNS SETOF record LANGUAGE 'plpgsql'  AS
...
Или еще вопросы будут?
Проблема аналогичная, но количество и название выходных столбцов неизвестно заранее - SQL генерируется динамически и потом выдаётся через
Код: plaintext
1.
2.
3.
   FOR rec in execute (sql) LOOP
            return next rec;
   END LOOP;
Есть ли варианты решения?
...
Рейтинг: 0 / 0
31.07.2006, 10:54
    #33888439
domanix
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
как вернуть рекордсет из функции?
Нет в таком случае нужно указывать внешнему запросу вызвавшему такую функцияю какие колонки и какого типа вернутся.
в противном случае парсер и планировщик не смогут узнать а какие типы и какие колонки возвращает данная функция.
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
create or replace function MayRecords ( in sql text)
RETURNS SETOF record AS
$body$
declare rr record;
begin
FOR rr in execute (sql) LOOP

           return next rr ;
END LOOP;
end
$body$
LANGUAGE 'plpgsql';

select  * from  MyRecords('select oid::integer,relname::text from pg_class') as (id integer,name text)
...
Рейтинг: 0 / 0
31.07.2006, 12:58
    #33888911
Vladimir Lavrentiev
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
как вернуть рекордсет из функции?
domanix
Код: plaintext
1.
select  * from  MyRecords('select oid::integer,relname::text from pg_class') as (id integer,name text)

Спасибо, так и сделал.
...
Рейтинг: 0 / 0
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / как вернуть рекордсет из функции? / 19 сообщений из 19, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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