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

Executando consultas dinamicamente em PL/pgSQL

Estatísticas do sistema


Antes de lançar o seu, dê uma olhada na tabela do sistema pg_statistic ou a visualização pg_stats :

Ele já pode ter algumas das estatísticas que você está prestes a calcular. É preenchido por ANALYZE , então você pode executar isso para novas (ou quaisquer) tabelas antes de verificar.
-- ANALYZE tbl;  -- optionally, to init / refresh
SELECT * FROM pg_stats
WHERE tablename = 'tbl'
AND   schemaname = 'public';

Função plpgsql dinâmica genérica


Você deseja retornar o valor mínimo para cada coluna em uma determinada tabela . Esta não é uma tarefa trivial, porque uma função (como SQL em geral) exige saber o tipo de retorno no momento da criação - ou pelo menos no momento da chamada com a ajuda de tipos de dados polimórficos.

Esta função faz tudo de forma automática e segura. Funciona para qualquer tabela, desde que a função agregada min() é permitido para cada coluna. Mas você precisa para conhecer o PL/pgSQL.
CREATE OR REPLACE FUNCTION f_min_of(_tbl anyelement)
  RETURNS SETOF anyelement
  LANGUAGE plpgsql AS
$func$
BEGIN
RETURN QUERY EXECUTE (
   SELECT format('SELECT (t::%2$s).* FROM (SELECT min(%1$s) FROM %2$s) t'
                , string_agg(quote_ident(attname), '), min(' ORDER BY attnum)
                , pg_typeof(_tbl)::text)
   FROM   pg_attribute
   WHERE  attrelid = pg_typeof(_tbl)::text::regclass
   AND    NOT attisdropped  -- no dropped (dead) columns
   AND    attnum > 0        -- no system columns
   );
END
$func$;

Ligue (importante!):
SELECT * FROM f_min_of(NULL::tbl);  -- tbl being the table name

db<>fiddle aqui
Antigo sqlfiddle

Você precisa entender esses conceitos:
  • SQL dinâmico em plpgsql com EXECUTE
  • Tipos polimórficos
  • Tipos de linha e tipos de tabela no Postgres
  • Como se defender contra injeção de SQL
  • Funções agregadas
  • Catálogos do sistema

Resposta relacionada com explicação detalhada:

Dificuldade especial com incompatibilidade de tipo


Estou aproveitando o Postgres definindo um tipo de linha para cada tabela existente. Usando o conceito de tipos polimórficos eu sou capaz de criar um função que funciona para qualquer tabela.

No entanto, algumas funções agregadas retornam tipos de dados relacionados, mas diferentes, em comparação com a coluna subjacente. Por exemplo, min(varchar_column) retorna text , que é compatível com bits, mas não exatamente o mesmo tipo de dados. As funções PL/pgSQL têm um ponto fraco aqui e insistem em tipos de dados exatamente conforme declarado no RETURNS cláusula. Nenhuma tentativa de cast, nem mesmo casts implícitos, para não falar de casts de atribuição.

Isso deve ser melhorado. Testado com Postgres 9.3. Não testei novamente com 9.4, mas tenho certeza que nada mudou nessa área.

É aí que essa construção entra como solução alternativa :
SELECT (t::tbl).* FROM (SELECT ... FROM tbl) t;

Ao converter a linha inteira para o tipo de linha da tabela subjacente explicitamente, forçamos as conversões de atribuição para obter os tipos de dados originais para cada coluna.

Isso pode falhar para alguma função agregada. sum() retorna numeric para uma sum(bigint_column) para acomodar uma soma que estoura o tipo de dados base. Transmitindo de volta para bigint pode falhar...