В postgres (plpgsql) как сделать функцию, которая возвращает select * для переменной table_name? - PullRequest
1 голос
/ 28 марта 2011

В принципе, по крайней мере, для подтверждения концепции, я хочу функцию, которую я могу запустить: SELECT res ('имя_таблицы'); и это даст мне результаты SELECT * FROM table_name ;. У меня проблема в схеме ... в объявлении функции, которую я имею:

СОЗДАТЬ ИЛИ ЗАМЕНИТЬ ФУНКЦИЮ res (имя_таблицы TEXT) ВОЗВРАЩАЕТСЯ НА ЭТОМ ПРОБЛЕМУ AS

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

Есть идеи?

Ответы [ 3 ]

7 голосов
/ 28 марта 2011

Вы можете сделать это, но, как упоминалось ранее, вам нужно добавить список определений столбцов в запросе SELECT.

CREATE OR REPLACE FUNCTION res(table_name TEXT)  RETURNS SETOF record AS $$
BEGIN
  RETURN QUERY EXECUTE 'SELECT * FROM ' || table_name;
END;
$$ LANGUAGE plpgsql;


SELECT * FROM res('sometable') sometable (col1 INTEGER, col2 INTEGER, col3 SMALLINT, col4 TEXT);
4 голосов
/ 28 марта 2011

Почему для каких-либо реальных практических целей вы просто хотите перейти в таблицу и выбрать * из нее?Может быть, ради забавы?

Вы не можете сделать это без определения какого-то известного выхода, такого как Джек и Руди-шоу.Или делать это так, как это делает depesz, используя выходные параметры http://www.depesz.com/index.php/2008/05/03/waiting-for-84-return-query-execute-and-cursor_tuple_fraction/.

Несколько хакерских подходов к стене - выдавать уведомления о повышении в цикле и распечатывать набор результатов по одной строке за раз.Или вы можете создать функцию get_rows_TABLENAME, которая имеет определение для каждой таблицы, которую вы хотите вернуть.Просто используйте код для генерации процедур создания.Но опять-таки не уверен, сколько значения делает выбор * из таблицы, особенно без каких-либо ограничений, кроме как для забавы или для того, чтобы кровь администратора БАД кипела.

Теперь в SQL Server вы можете иметь хранимую процедуру, возвращающую динамическийнабор результатов.Это и благословение, и проклятие, так как вы не можете быть уверены, что получится, не взглянув на определение.Для меня я смотрю на реализацию PostgreSQL как на более разумный способ сделать это.

2 голосов
/ 28 марта 2011

Даже если вам удастся это сделать (см. Ответ Руди-Мура, если у вас 8.4 или выше), вам придется явно расширить тип в select - например:

SELECT res('table_name') as foo(id int,...)
...