PostgreSQL
 sql >> Base de données >  >> RDS >> PostgreSQL

Fonction plpgsql :renvoie les lignes d'une vue créée à partir d'une table aléatoire

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 de tmp à la place.

  • Utilisez RETURN QUERY pour renvoyer un ensemble d'enregistrements. Cela peut même être un appel statique sans EXECUTE . 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