PostgreSQL - Écrire du sql dynamique dans une procédure stockée qui renvoie un jeu de résultats
Comment puis-je écrire une procédure stockée qui contient un construit dynamiquement instruction SQL qui retourne un jeu de résultats? Voici mon exemple de code:
CREATE OR REPLACE FUNCTION reporting.report_get_countries_new (
starts_with varchar,
ends_with varchar
)
RETURNS TABLE (
country_id integer,
country_name varchar
) AS
$body$
DECLARE
starts_with ALIAS FOR $1;
ends_with ALIAS FOR $2;
sql VARCHAR;
BEGIN
sql = 'SELECT * FROM lookups.countries WHERE lookups.countries.country_name >= ' || starts_with ;
IF ends_with IS NOT NULL THEN
sql = sql || ' AND lookups.countries.country_name <= ' || ends_with ;
END IF;
RETURN QUERY EXECUTE sql;
END;
$body$
LANGUAGE 'plpgsql'
VOLATILE
CALLED ON NULL INPUT
SECURITY INVOKER
COST 100 ROWS 1000;
Ce code renvoie une erreur:
ERROR: syntax error at or near "RETURN"
LINE 1: RETURN QUERY SELECT * FROM omnipay_lookups.countries WHERE o...
^
QUERY: RETURN QUERY SELECT * FROM omnipay_lookups.countries WHERE omnipay_lookups.countries.country_name >= r
CONTEXT: PL/pgSQL function "report_get_countries_new" line 14 at EXECUTE statement
J'ai essayé d'autres façons au lieu de cela:
RETURN QUERY EXECUTE sql;
Voie 1:
RETURN EXECUTE sql;
Chemin 2:
sql = 'RETURN QUERY SELECT * FROM....
/*later*/
EXECUTE sql;
Dans tous les cas, sans succès.
En fin de compte, je veux écrire une procédure stockée qui contient une instruction sql dynamique et qui retourne le résultat de l'instruction sql dynamique.
Postgres' version?
OriginalL'auteur prince | 2012-08-14
Vous devez vous connecter pour publier un commentaire.
Il y a place pour des améliorations:
Les points principaux
PostgreSQL 8.4 introduit la
USING
clause deEXECUTE
, ce qui est utile pour plusieurs raisons. Récapitulation dans le manuel:OIE, il est plus sûr et plus rapide que la construction d'une chaîne de requête avec le texte de la représentation des paramètres, même lorsque désinfectés avec
quote_literal()
.Notez que
$1, $2
dans la chaîne de requête, reportez-vous aux valeurs fournies dans leUSING
clause, pas pour les paramètres de la fonction.Lorsque vous revenez
SELECT * FROM lookups.countries
, vous pouvez simplifier leRETURN
déclaration comme démontré:Dans PostgreSQL, il y a un type composite défini pour chaque table automatiquement. L'utiliser. L'effet est que la fonction dépend du type et vous obtenez un message d'erreur si vous tentez de modifier le tableau. Drop & recréer la fonction dans un tel cas.
Cela peut ou peut ne pas être souhaitable - généralement il est! Vous souhaitez être mis au courant des effets secondaires si vous modifier les tables. La façon dont vous l'avez, votre fonction serait de briser le silence et lever une exception sur le prochain appel.
Si vous fournissez un par défaut explicite pour le deuxième paramètre dans la déclaration, comme l'a démontré, vous pouvez (mais ne pas le faire) simplifier l'appel dans le cas où vous ne souhaitez pas définir une limite supérieure avec
ends_with
.au lieu de:
Être conscient de surcharge de fonctions dans ce contexte.
Ne cite pas le nom de la langue
même si c'est toléré (pour l'instant). C'est un identificateur.'plpgsql'Vous pouvez affecter une variable au moment de la déclaration. Enregistre une étape supplémentaire.
Paramètres sont nommés dans l'en-tête. Baisse de l'absurde lignes:
quote_literal()
n'est pas applicable avecUSING
, ce qui évite la conversion en texte littéral et le besoin de citer tout à fait. Il est dans mon explication.existe-il des nouvelles considérations pour PostgreSQL 9.3?
C'est tout bon jusqu'à la version actuelle 9.4. Liées à répondre avec plus de détails: stackoverflow.com/questions/17353445/...
belle, merci!
OriginalL'auteur Erwin Brandstetter
Utilisation quote_literal() pour éviter L'injection SQL (!!!) et de réparer vos citant problème:
C'est testé dans la version 9.1, fonctionne très bien.
OriginalL'auteur Frank Heikens