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

PostgreSQL - Écriture SQL dynamique dans une procédure stockée qui renvoie un ensemble de résultats

Des améliorations sont possibles :

CREATE OR REPLACE FUNCTION report_get_countries_new (starts_with text
                                                   , ends_with   text = NULL)
  RETURNS SETOF lookups.countries AS
$func$
DECLARE
   sql text := 'SELECT * FROM lookups.countries WHERE country_name >= $1';
BEGIN
   IF ends_with IS NOT NULL THEN
      sql := sql || ' AND country_name <= $2';
   END IF;

   RETURN QUERY EXECUTE sql
   USING starts_with, ends_with;
END
$func$ LANGUAGE plpgsql;
-- the rest is default settings

Points majeurs

  • PostgreSQL 8.4 a introduit le USING clause pour EXECUTE , ce qui est utile pour plusieurs raisons. Récapitulatif dans le manuel :

    La chaîne de commande peut utiliser des valeurs de paramètre, qui sont référencées dans la commande sous la forme $1, $2 , etc. Ces symboles font référence aux valeurs fournies dans le champ USING clause. Cette méthode est souvent préférable à l'insertion de valeurs de données dans la chaîne de commande sous forme de texte :elle évite la surcharge d'exécution liée à la conversion des valeurs en texte et inversement, et elle est beaucoup moins sujette aux attaques par injection SQL puisqu'il n'est pas nécessaire de mettre des guillemets ou d'échapper.

    IOW, il est plus sûr et plus rapide que de créer une chaîne de requête avec une représentation textuelle des paramètres, même lorsqu'il est nettoyé avec quote_literal() .
    Notez que $1, $2 dans la chaîne de requête, faites référence aux valeurs fournies dans le USING clause, pas aux paramètres de la fonction.

  • Pendant que vous renvoyez SELECT * FROM lookups.countries , vous pouvez simplifier le RETURN déclaration comme démontré :

    RETURNS SETOF lookups.countries
    

    Dans PostgreSQL, un type composite est défini automatiquement pour chaque table. Utilise le. L'effet est que la fonction dépend du type et vous obtenez un message d'erreur si vous essayez de modifier la table. Supprimez et recréez la fonction dans un tel cas.

    Cela peut être souhaitable ou non - c'est généralement le cas ! Vous voulez être informé des effets secondaires si vous modifiez les tables. De la façon dont vous l'avez, votre fonction s'interromprait silencieusement et déclencherait une exception lors de son prochain appel.

  • Si vous fournissez une valeur explicite par défaut pour le deuxième paramètre de la déclaration comme démontré, vous pouvez (mais vous n'êtes pas obligé) simplifier l'appel au cas où vous ne voudriez pas définir une limite supérieure avec ends_with .

    SELECT * FROM report_get_countries_new('Zaire');
    

    au lieu de :

    SELECT * FROM report_get_countries_new('Zaire', NULL);
    

    Soyez conscient de la surcharge de fonctions dans ce contexte.

  • Ne citez pas le nom de la langue 'plpgsql' même si c'est toléré (pour l'instant). C'est un identifiant.

  • Vous pouvez affecter une variable au moment de la déclaration. Enregistre une étape supplémentaire.

  • Les paramètres sont nommés dans l'en-tête. Supprimez les lignes absurdes :

     starts_with ALIAS FOR $1;
     ends_with ALIAS FOR $2;