powered by simpleCommunicator - 2.0.60     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / как вернуть рекордсет из функции?
19 сообщений из 19, страница 1 из 1
как вернуть рекордсет из функции?
    #33869958
Winnipuh
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Я могу вернуть RETURNS SETOF integer.

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

Как ?
...
Рейтинг: 0 / 0
как вернуть рекордсет из функции?
    #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
как вернуть рекордсет из функции?
    #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
как вернуть рекордсет из функции?
    #33870066
Winnipuh
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
определил композитный тип, в принципе - нормальное, быстрое решение

(Y)
...
Рейтинг: 0 / 0
как вернуть рекордсет из функции?
    #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
как вернуть рекордсет из функции?
    #33870112
4321
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Winnipuhспасибо,
вот функция, компилируется нормально, но при выборке пишет ошибку

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

SELECT для ф-ии с типом "рекорд" требует указания "листа определения колонок"
т.е. определение типа вывода переносится на этап SELECT-а .
Все см в доке, или тут - поиском (возможно - по фрагменту сообщения).
...
Рейтинг: 0 / 0
как вернуть рекордсет из функции?
    #33870152
domanix
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
то :4321
в восьмерке появились параметры in и out
и необходимость определять тип результата функции или указывать список колонок для типа record уже отпала.
так что ежели у воспрошающего pG 8 - то пусть пишет как я привел выше. Это значительно облегчает жизнь.. Ежели не 8 тады ой....
...
Рейтинг: 0 / 0
как вернуть рекордсет из функции?
    #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
как вернуть рекордсет из функции?
    #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
как вернуть рекордсет из функции?
    #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
как вернуть рекордсет из функции?
    #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
как вернуть рекордсет из функции?
    #33871127
4321
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Winnipuh2 domanix:
увы, нужна, самое интересное за этим скрыто

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

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

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

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


не совсем понял Вашу идею. как?...
...
Рейтинг: 0 / 0
как вернуть рекордсет из функции?
    #33871192
Winnipuh
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
в T-SQL я избавился от рекурсии. Возможно здесь рекурсивно обойти?...
...
Рейтинг: 0 / 0
как вернуть рекордсет из функции?
    #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
как вернуть рекордсет из функции?
    #33871236
4321
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
что вам мешает открывать рекордсет не по селекту к таблице, а скажем по выборке вида:
select * from myrecordset(100);

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

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

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

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

ах да, вспомнил. Вы еще можете захотеть менять данные темповой выборки руками (с тем, чтобы потом куда-то влить). Если это - ваш случай, то видимо да, вам будет удобно работать с темповой.
...
Рейтинг: 0 / 0
как вернуть рекордсет из функции?
    #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
как вернуть рекордсет из функции?
    #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
как вернуть рекордсет из функции?
    #33888911
Vladimir Lavrentiev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
domanix
Код: plaintext
1.
select  * from  MyRecords('select oid::integer,relname::text from pg_class') as (id integer,name text)

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


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