Cela pourrait fonctionner comme ceci :
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;
-
Notez l'utilisation du type d'identifiant d'objet
regclass
pour éviter automatiquement l'injection SQL. -
N'utilisez pas la syntaxe obsolète
var ALIAS for $1
si vous n'êtes pas obligé. Déclarez plutôt les noms des paramètres. -
Je n'utiliserais pas le mot-clé
temp
comme identifiant, même si cela est autorisé. Utilisation detmp
à la place. -
Utilisez
RETURN QUERY
pour renvoyer un ensemble d'enregistrements. Cela peut même être un appel statique sansEXECUTE
. Cependant, vous renvoyez des enregistrements anonymes et Postgres exige une liste de définition de colonne à chaque appel :
SELECT * FROM tt_query('tbl_name', '2014-02-15 12:00')
AS f(col1 int, col2 text, ...);
C'est plutôt lourd.
Meilleures solutions
Si vous savez le type de retour (même si les noms de table changent, la liste des colonnes peut partager les mêmes types), déclarez-le au moment de la création. Considérez cette question connexe :
PostgreSQL :ERREUR :42601 :une liste de définition de colonne est requise pour les fonctions renvoyant "record"
Si le type de retour varie avec le nom de table fourni, il existe toujours une bien meilleure solution. Puisque vous créez une vue avec SELECT * FROM tbl
, vous pouvez utiliser le type bien connu de la table elle-même comme polymorphe
paramètre :
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;
Appel simplifié :
SELECT * FROM tt_query(NULL::tbl_name, '2014-02-15 12:00');
En utilisant également format()
pour une concaténation de chaînes sûre et simple.
Plus de détails dans cette réponse connexe :
Refactoriser une fonction PL/pgSQL pour renvoyer la sortie de diverses requêtes SELECT