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

ERREUR Postgres pl/pgsql :la colonne nom_colonne n'existe pas

Votre fonction pourrait ressembler à ceci :

CREATE FUNCTION select_transactions3(_col text, _val text, _limit int)    
  RETURNS SETOF transactions AS   
$BODY$   
BEGIN

RETURN QUERY EXECUTE '
   SELECT *
   FROM   transactions
   WHERE  ' || quote_ident(_col) || ' = $1
   LIMIT  $2'
USING _val, _limit;

END;   
$BODY$  
LANGUAGE plpgsql VOLATILE SECURITY DEFINER;

EN PostgreSQL 9.1 ou plus tard c'est plus simple avec le format format()

...
RETURN QUERY EXECUTE format('
   SELECT *
   FROM   transactions
   WHERE  %I = $1
   LIMIT  $2', _col)
USING _val, _limit;
...

%I échappe les identifiants comme quote_ident() .

Points majeurs :

  • Vous vous heurtiez à la limitation du SQL dynamique selon laquelle vous ne pouvez pas utiliser de paramètres pour les identificateurs. Vous devez construire la chaîne de requête avec le nom de la colonne et puis exécutez-le.

  • Vous pouvez cependant le faire avec des valeurs. Je démontre l'utilisation du USING clause pour EXECUTE . Notez également l'utilisation de quote_ident() :empêche l'injection SQL et certaines erreurs de syntaxe.

  • J'ai aussi grandement simplifié votre fonction. [RETURN QUERY EXECUTE][3] rend votre code plus court et plus rapide. Pas besoin de boucler si tout ce que vous faites est de retourner la ligne.

  • J'utilise nommé IN paramètres, afin de ne pas être confondu avec la notation $ dans la chaîne de requête. $1 et $2 à l'intérieur de la chaîne de requête, faites référence aux valeurs fournies dans le USING clause, pas aux paramètres d'entrée.

  • Je passe à SELECT * car vous devez de toute façon renvoyer la ligne entière pour correspondre au type de retour déclaré.

  • Dernier point mais non le moindre :assurez-vous de tenir compte de ce que le manuel a à dire sur les fonctions déclarées SECURITY DEFINER .

TYPE DE RETOUR

Si vous ne souhaitez pas renvoyer la ligne entière, une possibilité pratique est :

CREATE FUNCTION select_transactions3(_col text, _val text, _limit int)    
  RETURNS TABLE (invoice_no varchar(125), amount numeric(12,2) AS ...

Ainsi, vous n'êtes pas obligé de fournir une liste de définitions de colonne à chaque appel et vous pouvez simplifier :

SELECT * FROM select_to_transactions3('invoice_no', '1103300105472', 1);