PostgreSQL
 sql >> Database >  >> RDS >> PostgreSQL

Funzione plpgsql:restituisce le righe da una vista creata da una tabella casuale

Potrebbe funzionare così:

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;
  • Nota l'uso del tipo di identificatore oggetto regclass per evitare automaticamente l'iniezione SQL.

  • Non utilizzare la sintassi obsoleta var ALIAS for $1 se non è necessario. Dichiara invece i nomi dei parametri.

  • Non userei la parola chiave temp come identificatore, anche se consentito. Usando tmp invece.

  • Usa RETURN QUERY per restituire una serie di record. Può anche essere una chiamata statica senza EXECUTE . Tuttavia, stai restituendo record anonimi e Postgres richiede un elenco di definizione delle colonne ad ogni chiamata:

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

Questo è piuttosto ingombrante.

Soluzioni migliori

Se sai il tipo restituito (anche se i nomi delle tabelle stanno cambiando, l'elenco di colonne potrebbe condividere gli stessi tipi), dichiararlo al momento della creazione. Considera questa domanda correlata:
PostgreSQL:ERRORE:42601:è richiesto un elenco di definizioni di colonna per le funzioni che restituiscono "record"

Se il tipo di reso varia con il nome della tabella fornito, c'è ancora una soluzione molto migliore. Poiché stai creando una vista con SELECT * FROM tbl , puoi utilizzare il tipo noto della tabella stessa come polimorfi parametro:

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;

Chiamata semplificata:

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

Usando anche format() per una concatenazione di stringhe semplice e sicura.

Maggiori dettagli in questa risposta correlata:
Refactoring di una funzione PL/pgSQL per restituire l'output di varie query SELECT