Não há nada de errado com uma função plpgsql para algo um pouco mais complexo. A única situação em que o desempenho pode sofrer é quando uma função plpgsql está aninhada, porque o planejador de consulta não pode otimizar ainda mais o código contido no contexto da consulta externa, o que pode ou não torná-la mais lenta.
Mais detalhes mais adiante responda:
- Diferença entre linguagem sql e linguagem plpgsql nas funções do PostgreSQL
No caso em questão é muito mais simples do que muitos
CASE
cláusulas em uma consulta:CREATE OR REPLACE FUNCTION get_stuff(_param text, _orderby text, _limit int)
RETURNS SETOF stuff AS
$func$
BEGIN
RETURN QUERY EXECUTE '
SELECT *
FROM stuff
WHERE col = $1
ORDER BY ' || quote_ident(_orderby) || ' ASC
LIMIT $2'
USING _param, _limit;
END
$func$ LANGUAGE plpgsql;
Ligar:
SELECT * FROM get_stuff('hello', 'col2', 100);
Observações
Use
RETURN QUERY EXECUTE
para retornar os resultados da consulta de uma só vez. Use
quote_ident()
para identificadores para proteção contra SQLi.Ou
format()
para algo mais complexo. Ver:- Nome da tabela como parâmetro de função do PostgreSQL
Passe valores de parâmetro com o
USING
cláusula para evitar conversão, citação e SQLi mais uma vez. Tenha cuidado para não criar conflitos de nomenclatura entre parâmetros e nomes de coluna. Eu prefixei nomes de parâmetros com um sublinhado (
_
) no exemplo. Apenas minha preferência pessoal. Sua segunda função após a edição não pode funcionar, porque você retorna apenas
parent
enquanto o tipo de retorno é declarado SETOF stuff
. Você pode declarar qualquer tipo de retorno que você gosta, mas os valores de retorno reais precisam corresponder à declaração. Você pode querer usar RETURNS TABLE
por isso.