sql >> Base de Datos >  >> RDS >> PostgreSQL

Ejecutando consultas dinámicamente en PL/pgSQL

Estadísticas del sistema

Antes de lanzar el suyo, eche un vistazo a la tabla del sistema pg_statistic o la vista pg_stats :

Es posible que ya tenga algunas de las estadísticas que está a punto de calcular. Está poblado por ANALYZE , por lo que puede ejecutar eso para tablas nuevas (o cualquier) antes de verificar.

-- ANALYZE tbl;  -- optionally, to init / refresh
SELECT * FROM pg_stats
WHERE tablename = 'tbl'
AND   schemaname = 'public';

Función plpgsql dinámica genérica

Quiere devolver el valor mínimo para cada columna en una tabla determinada . Esta no es una tarea trivial, porque una función (como SQL en general) exige conocer el tipo de devolución en el momento de la creación, o al menos en el momento de la llamada con la ayuda de tipos de datos polimórficos.

Esta función hace todo de forma automática y segura. Funciona para cualquier tabla, siempre que la función agregada min() está permitido para cada columna. Pero necesitas para familiarizarse con 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$;

Llame (¡importante!):

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

db<>fiddle aquí
Antiguo sqlfiddle

Necesita comprender estos conceptos:

  • SQL dinámico en plpgsql con EXECUTE
  • Tipos polimórficos
  • Tipos de filas y tipos de tablas en Postgres
  • Cómo defenderse de la inyección SQL
  • Funciones agregadas
  • Catálogos del sistema

Respuesta relacionada con explicación detallada:

Dificultad especial con tipo de desajuste

Estoy aprovechando que Postgres define un tipo de fila para cada tabla existente. Usando el concepto de tipos polimórficos puedo crear uno función que funciona para cualquier tabla.

Sin embargo, algunas funciones agregadas devuelven tipos de datos relacionados pero diferentes en comparación con la columna subyacente. Por ejemplo, min(varchar_column) devuelve text , que es compatible con bits, pero no exactamente el mismo tipo de datos. Las funciones PL/pgSQL tienen un punto débil aquí e insisten en los tipos de datos exactamente como se declara en RETURNS cláusula. Ningún intento de lanzar, ni siquiera lanzamientos implícitos, por no hablar de lanzamientos de asignación.

Eso debería mejorarse. Probado con Postgres 9.3. No volví a probar con 9.4, pero estoy bastante seguro de que nada ha cambiado en esta área.

Ahí es donde entra esta construcción como solución alternativa :

SELECT (t::tbl).* FROM (SELECT ... FROM tbl) t;

Al convertir toda la fila al tipo de fila de la tabla subyacente de forma explícita, forzamos las conversiones de asignación para obtener tipos de datos originales para cada columna.

Esto podría fallar para alguna función agregada. sum() devuelve numeric para una sum(bigint_column) para acomodar una suma que desborda el tipo de datos base. Volviendo a bigint podría fallar...