Возврат строк 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-запрос для начала. Не функция.
есть более продвинутые варианты, но вам может понадобиться, чтобы изучить основы.