PostgreSQL
 sql >> Base de Dados >  >> RDS >> PostgreSQL

Retorna as linhas correspondentes aos elementos da matriz de entrada na função plpgsql


Isso funciona:
CREATE OR REPLACE FUNCTION avg_purchases(last_names text[] = '{}')
  RETURNS TABLE(last_name text, avg_purchase_size float8) AS
$func$
   SELECT last_name, AVG(purchase_size)::float8
   FROM   purchases
   WHERE  last_name = ANY($1)
   GROUP  BY last_name
$func$  LANGUAGE sql;

Ligar:
SELECT * FROM avg_purchases('{foo,Bar,baz,"}weird_name''$$"}');

Ou (atualização - exemplo com cotação do dólar):
SELECT * FROM avg_purchases($x${foo,Bar,baz,"}weird_name'$$"}$x$);

  • Mais sobre como citar literais de string:
    Inserir texto com aspas simples no PostgreSQL

  • Você não precisa de SQL dinâmico aqui.

  • Enquanto você pode envolvê-lo em uma função plpgsql (que pode ser útil), uma função SQL simples está fazendo o trabalho muito bem.

  • Você tem incompatibilidades de tipo .
    • o resultado de avg() pode ser numeric para manter um resultado preciso. Transmito para float8 para fazê-lo funcionar, que é apenas um alias para double precision (você pode usar qualquer um). Se você precisa de precisão perfeita, use numeric em vez disso.
    • Desde que você GROUP BY last_name você quer um text simples Parâmetro OUT em vez de text[] .

VARIADIC


Uma matriz é um tipo útil de entrada. Se for mais fácil para o seu cliente, você também pode usar um VARIADIC parâmetro de entrada que permite passar o array como uma lista de elementos :
CREATE OR REPLACE FUNCTION avg_purchases(VARIADIC last_names text[] = '{}')
  RETURNS TABLE(last_name text, avg_purchase_size float8) AS
$func$
   SELECT last_name, AVG(purchase_size)::float8
   FROM   purchases
   JOIN  (SELECT unnest($1)) t(last_name) USING (last_name)
   GROUP  BY last_name
$func$  LANGUAGE sql;

Ligar:
SELECT * FROM avg_purchases('foo', 'Bar', 'baz', '"}weird_name''$$"}');

Ou (com cotação do dólar):
SELECT * FROM avg_purchases('foo', 'Bar', 'baz', $y$'"}weird_name'$$"}$y$);

Esteja ciente de que o Postgres padrão permite apenas um máximo de 100 elementos . Isso é determinado em tempo de compilação pela opção predefinida:

max_function_args (integer)

Informa o número máximo de argumentos de função. É determinado pelo valor de FUNC_MAX_ARGS ao construir o servidor. O valor padrão é 100 argumentos.

Você ainda pode chamá-lo com notação de array quando prefixado com a palavra-chave VARIADIC :
SELECT * FROM avg_purchases(VARIADIC '{1,2,3, ... 99,100,101}');

Para matrizes maiores (mais de 100), eu também usaria unnest() em uma subconsulta e JOIN para ele, que tende a escalar melhor:
  • Otimizando uma consulta Postgres com um grande IN