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

Función plpgsql:devuelve filas de una vista creada a partir de una tabla aleatoria

Podría funcionar así:

CREATE OR REPLACE FUNCTION tt_query(orig_name regclass, data_tt timestamp)
  RETURNS SETOF record AS
$func$
BEGIN

EXECUTE 'CREATE OR REPLACE TEMP VIEW tmp as 
select * 
from  '
|| orig_name 
|| ' where trigger_changed >'
|| quote_literal(data_tt)
|| ' ORDER BY trigger_changed DESC';

-- other work on view tmp

-- return the rows of view temp
RETURN QUERY
SELECT * FROM tmp;

END
$func$  LANGUAGE plpgsql;
  • Tenga en cuenta el uso del tipo de identificador de objeto regclass para evitar automáticamente la inyección de SQL.

  • No use la sintaxis obsoleta var ALIAS for $1 si no es necesario. Declare los nombres de los parámetros en su lugar.

  • No usaría la palabra clave temp como identificador, incluso si eso está permitido. Usando tmp en su lugar.

  • Utilice RETURN QUERY para devolver un conjunto de registros. Incluso puede ser una llamada estática sin EXECUTE . Sin embargo, está devolviendo registros anónimos y Postgres exige una lista de definición de columna con cada llamada:

SELECT * FROM tt_query('tbl_name', '2014-02-15 12:00')
AS f(col1 int, col2 text, ...);

Esto es bastante difícil de manejar.

Mejores soluciones

Si sabes el tipo de devolución (incluso si los nombres de las tablas están cambiando, la lista de columnas puede compartir los mismos tipos), declararlo en el momento de la creación. Considere esta pregunta relacionada:
PostgreSQL:ERROR:42601:se requiere una lista de definición de columna para las funciones que devuelven "registro"

Si el tipo de devolución varía con el nombre de la tabla proporcionado, todavía hay una solución mucho mejor. Dado que está creando una vista con SELECT * FROM tbl , puede utilizar el tipo conocido de la tabla en sí como polimórfico parámetro:

CREATE OR REPLACE FUNCTION tt_query(orig_name anyelement, data_tt timestamp)
  RETURNS SETOF anyelement AS
$func$
BEGIN

EXECUTE format('CREATE OR REPLACE TEMP VIEW tmp AS
   SELECT * FROM  %s
   WHERE  trigger_changed > %L
   ORDER  BY trigger_changed DESC'
  ,pg_typeof(orig_name)
  ,data_tt);

-- other work on view tmp

-- return the rows of view tmp
RETURN QUERY
SELECT * FROM tmp;

END
$func$  LANGUAGE plpgsql;

Llamada simplificada:

SELECT * FROM tt_query(NULL::tbl_name, '2014-02-15 12:00');

También usando format() para una concatenación de cadenas segura y sencilla.

Más detalles en esta respuesta relacionada:
Refactorizar una función PL/pgSQL para devolver el resultado de varias consultas SELECT