Возврат строк SETOF из функции PostgreSQL

У меня ситуация, когда я хочу вернуть соединение между двумя видами. и это много колонок. Это было довольно легко в sql server. Но в PostgreSQL, когда я делаю соединение. Я получаю сообщение об ошибке"требуется список определений столбцов".

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

CREATE OR REPLACE FUNCTION functionA(username character varying DEFAULT ''::character varying, databaseobject character varying DEFAULT ''::character varying)
  RETURNS SETOF ???? AS
$BODY$
Declare 
SqlString varchar(4000) = '';
BEGIN
IF(UserName = '*') THEN
   Begin
   SqlString  := 'select * from view1 left join ' + databaseobject  + ' as view2 on view1.id = view2.id';
   End;
ELSE
    Begin
    SqlString := 'select * from view3 left join ' + databaseobject  + ' as view2 on view3.id = view2.id';
    End;
END IF; 
execute (SqlString  );
END;
$BODY$

1 ответов


санировать функция

руководство имеет все основы для PL / pgSQL. В принципе, то, что у вас есть, можно упростить / санировать до:

CREATE OR REPLACE FUNCTION func_a(username text = '', databaseobject text = '')
  RETURNS ???? AS
$func$
BEGIN

RETURN QUERY EXECUTE
format ('SELECT * FROM %s v1 LEFT JOIN %I v2 USING (id)'
       , CASE WHEN username = '*' THEN 'view1' ELSE 'view3' END, databaseobject);

END
$func$  LANGUAGE plpgsql;
  • вам не нужны дополнительные экземпляры BEGIN .. END в теле функции за исключением запуска отдельного блока кода со своей собственной областью, которая редко требуется.

  • стандартным оператором конкатенации SQL является ||. + - это "творческое" дополнение вашего бывшего поставщика.

  • не используйте идентификаторы CaMeL-case если вы дважды цитируете их. Лучше не использовать их вообще:

  • varchar(4000) также адаптирован к определенному ограничению SQL Server. Этот тип данных не имеет никаких преимуществ в Postgres. Используйте его, только если вам действительно нужен лимит 4000 символов. Я бы просто использовал text - за исключением того, что нам не нужны никакие переменные на всех здесь, после того, как я упростил функцию.

  • если вы не использовали format(), однако, обратитесь к руководству здесь.

тип возвращаемого

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

CREATE FUNCTION foo()
  RETURNS SETOF my_view AS
...

если вы делаете вид, как вы идете, вы можете либо вернуть анонимные записи:

CREATE FUNCTION foo()
  RETURNS SETOF record AS
...

или предоставить список определения столбца с (простейшим)RETURNS TABLE:

CREATE FUNCTION foo()
  RETURNS TABLE (col1 int, col2 text, ...) AS
...

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

я бы не стал использовать SELECT * для начала. Используйте окончательный список столбцов для возврата и объявления типа возврата соответственно:

CREATE OR REPLACE FUNCTION func_a(username text = '', databaseobject text = '')
  RETURNS TABLE(col1 int, col2 text, col3 date) AS
$func$
BEGIN

RETURN QUERY EXECUTE
format ('SELECT v1.col1, v1.col2, v2.col3
         FROM %s v1 LEFT JOIN %I v2 USING (id)$f$
       , CASE WHEN username = '*' THEN 'view1' ELSE 'view3' END, databaseobject);

END
$func$;

для полностью динамических запросов я бы предпочел использовать простой SQL-запрос для начала. Не функция.

есть более продвинутые варианты, но вам может понадобиться, чтобы изучить основы.