powered by simpleCommunicator - 2.0.60     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / Вывод из функции с переменным кол-вом полей
10 сообщений из 10, страница 1 из 1
Вывод из функции с переменным кол-вом полей
    #34852909
kuklyuk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Ситуация:
По замыслу, функция должна динамически генерировать текст запроса с переменным количеством полей (типа "перекрестного" запроса), и потом выводить результат этого запроса.

Суть проблемы:
Поскольку количество полей переменное, в выводе функции нельзя объявить RETURNS SETOF _Композитный_Тип_, поскольку у любого типа структура строго определена. А объявить RETURNS SETOF RECORD -- ругается "a column definition list is required for functions returning "record", т.е не определены колонки рекорда.

Как быть? Не получать же текст запроса в клиентскую часть, а потом снова пихать его серверу уже в текстовом виде... Глуповато получается, хотелось бы все реализовать в одной функции.
Поделитесь мыслями, плиз...
...
Рейтинг: 0 / 0
Вывод из функции с переменным кол-вом полей
    #34852956
Фотография Ёш
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
/topic/419461&hl=returns+setof+record

обратите внимание на формат вызова этой функции (с returns setof record) - SELECT * FROM foo() AS (c1 INTEGER, c2 INTEGER)

пожалуйста, пользуйтесь поиском, всё это много раз обсуждалось... :(


--
„Истина — это вовсе не то, что можно убедительно доказать, это то, что
делает всё проще и понятнее“ — Антуан де Сент-Экзюпери
...
Рейтинг: 0 / 0
Вывод из функции с переменным кол-вом полей
    #34853854
kuklyuk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Уважаемый Ёш!
Спасибо что откликнулись.
С форматом вызова функций возвращающих RECORD я уже сталкивался. Но как раз в нем и суть проблемы.

В предложенном Вами примере предложение "AS (c1 INTEGER, c2 INTEGER)" как раз задает тот самый недостающий column definition list, на который идет ругань в моей функции. Но дело в том что при вызове моей функции _неизвестно_, сколько полей вернется (зависит от количества записей в одной из объединяемых таблиц), поэтому нельзя при вызове задать конкретный column definition list.

В голову пока приходит только одна идея:

1)Сформировать в отдельной функции SQL-текст запроса (возвращается как текст);
2)Отдельно сформировать _в_текстовом_виде_ вызов функции, возвращающей RECORD, и предложение AS(...) к этому вызову, на основе того же количества полей, что и основной запрос.
3)Подсунуть это все функции (по типу Вашего примера), через Execute, передав SQL-текст как параметр, и предложив в вызове динамически сгенерированное предложение AS(...) .

Не слишком изящно выходит, но других направлений мысли пока не вижу.
Не попадались ли Вам другие, более оптимальные пути (возможно с использованием курсоров или еще как)?

(В любом случае спасибо за ответ.)
...
Рейтинг: 0 / 0
Вывод из функции с переменным кол-вом полей
    #34854066
st_serg
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
можно возвращать набор рефкусоров
...
Рейтинг: 0 / 0
Вывод из функции с переменным кол-вом полей
    #34854187
4321
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kuklyuk ... нельзя при вызове задать конкретный column definition list.


например можно сделать так
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
CREATE OR REPLACE FUNCTION test_test1()
  RETURNS SETOF RECORD AS
$BODY$

SELECT *
FROM test ;

$BODY$
  LANGUAGE 'sql' VOLATILE;
SELECT test_test1();

(или SELECT test_test1() as f;)
так как это срабатывает (по крайней мере вплоть до 8.1) , то разумно ожидать возможности такой модификации последнего запроса
Код: plaintext
SELECT * FROM test_test1() AS (f RECORD);
но тут же получим отлуп:
Код: plaintext
ERROR:  column "f" has pseudo-type record
(удивительное рядом - запрос SELECT test_test1() as f; возвращает именно колонку f с типом record)

добраться до содержимого по именам в исходном типе тоже не получается:
Код: plaintext
1.
SELECT f.name FROM (SELECT test_test1() as f)  as foo;
ERROR:  missing FROM-clause entry for table "f"
т.е. получить т.н. композитный тип можно, но как к нему "8.11.3. Accessing Composite Types" - не ясно (мне пока).
...
Рейтинг: 0 / 0
Вывод из функции с переменным кол-вом полей
    #34856021
Kruchinin Pahan
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
4321добраться до содержимого по именам в исходном типе тоже не получается:
Код: plaintext
1.
SELECT f.name FROM (SELECT test_test1() as f)  as foo;
ERROR:  missing FROM-clause entry for table "f"
т.е. получить т.н. композитный тип можно, но как к нему "8.11.3. Accessing Composite Types" - не ясно (мне пока).
Может так?
SELECT foo.name FROM (SELECT test_test1() as f) as foo;
Сам не проверял.
...
Рейтинг: 0 / 0
Вывод из функции с переменным кол-вом полей
    #34856386
4321
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Kruchinin Pahan Может так?
SELECT foo.name FROM (SELECT test_test1() as f) as foo;
Сам не проверял.да нет. дело в частности и в том, что если тип у поля в SELECT test_test1() - record, а не test, то и имен там нет, а вот так уже не работает:
SELECT test_test1()::test;
ERROR: cannot cast type record to test

а даже если бы работало, то нельзя никак:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
--SELECT foo.name FROM (SELECT test_test1() as f) as foo;
--ERROR:  column foo.name does not exist
--SELECT foo.f.name FROM (SELECT test_test1() as f) as foo;
--ERROR:  schema "foo" does not exist
--SELECT public.foo.f.name FROM (SELECT test_test1() as f) as foo;
--ERROR:  cross-database references are not implemented: public.foo.f.name
--SELECT f.name FROM (SELECT test_test1()::test as f) as foo;
--ERROR:  missing FROM-clause entry for table "f"
...
Рейтинг: 0 / 0
Вывод из функции с переменным кол-вом полей
    #34856954
Kruchinin Pahan
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
4321
а даже если бы работало, то нельзя никак:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
--SELECT foo.name FROM (SELECT test_test1() as f) as foo;
--ERROR:  column foo.name does not exist
--SELECT foo.f.name FROM (SELECT test_test1() as f) as foo;
--ERROR:  schema "foo" does not exist
--SELECT public.foo.f.name FROM (SELECT test_test1() as f) as foo;
--ERROR:  cross-database references are not implemented: public.foo.f.name
--SELECT f.name FROM (SELECT test_test1()::test as f) as foo;
--ERROR:  missing FROM-clause entry for table "f"

Да, я уже тоже подергал. Действительно не выкручивается. Была мысль закрутить RECORD в AnyElement[]. Где-то я даже подобное проворачивал, но может меня где-то склероз подводит.
...
Рейтинг: 0 / 0
Вывод из функции с переменным кол-вом полей
    #34857037
Kruchinin Pahan
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Kruchinin Pahan
Да, я уже тоже подергал. Действительно не выкручивается. Была мысль закрутить RECORD в AnyElement[]. Где-то я даже подобное проворачивал, но может меня где-то склероз подводит.
А еще я так подергал:
Код: plaintext
1.
2.
3.
4.
--SELECT (test_test1()).kod as f ;
--ERROR:  could not identify column "kod" in record data type
--SELECT (foo.f).kod FROM (SELECT test_test1() as f) as foo ;
--ERROR:  record type has not been registered
...
Рейтинг: 0 / 0
Вывод из функции с переменным кол-вом полей
    #34857054
Kruchinin Pahan
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Причем эта схема прекрасно работает, если тип возвращаемых данных определен как тип record таблицы, аггрегатный тип данных или record вьюшки.
...
Рейтинг: 0 / 0
10 сообщений из 10, страница 1 из 1
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / Вывод из функции с переменным кол-вом полей
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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