Je le ferais comme ceci :
CREATE OR REPLACE FUNCTION list(
_category varchar(100)
, _limit int
, _offset int
, _order_by varchar(100)
, _order_asc_desc text = 'ASC') -- last param with default value
RETURNS TABLE(id int, name varchar, clientname varchar, totalcount bigint)
LANGUAGE plpgsql AS
$func$
DECLARE
_empty text := '';
BEGIN
-- Assert valid _order_asc_desc
IF upper(_order_asc_desc) IN ('ASC', 'DESC', 'ASCENDING', 'DESCENDING') THEN
-- proceed
ELSE
RAISE EXCEPTION 'Unexpected value for parameter _order_asc_desc.
Allowed: ASC, DESC, ASCENDING, DESCENDING. Default: ASC';
END IF;
RETURN QUERY EXECUTE format(
'SELECT id, name, clientname, count(*) OVER() AS full_count
FROM design_list
WHERE ($1 = $2 OR category ILIKE $1)
ORDER BY %I %s
LIMIT %s
OFFSET %s'
, _order_by, _order_asc_desc, _limit, _offset)
USING _category, _empty;
END
$func$;
Fonctionnalité principale :utilisez le format format()
pour concaténer en toute sécurité et élégance votre chaîne de requête. Connexe :
- INSÉRER avec nom de table dynamique dans la fonction de déclenchement
- Spécificateur de format pour les variables entières dans format() pour EXECUTE ?
ASC
/ DESC
(ou ASCENDING
/ DESCENDING
) sont des mots clés fixes. J'ai ajouté une vérification manuelle (IF ...
) et ensuite concaténer avec un simple %s
. C'est un façon d'affirmer l'apport juridique. Pour plus de commodité, j'ai ajouté un message d'erreur pour une entrée inattendue et un paramètre par défaut, de sorte que la fonction par défaut est ASC
si le dernier paramètre est omis dans l'appel. Connexe :
- Argument facultatif en PL /fonction pgSQL
- ERREUR :les paramètres d'entrée après un avec une valeur par défaut doivent également avoir des valeurs par défaut dans Postgres
Adressage Pavel valide commentaire
, je concatène _limit
et _offset
directement, la requête est donc déjà planifiée avec ces paramètres.
_limit
et _offset
sont integer
paramètres, afin que nous puissions utiliser %s
sans risque d'injection SQL. Vous voudrez peut-être affirmer des valeurs raisonnables (exclure les valeurs négatives et les valeurs trop élevées) avant de concaténer ...
-
Utilisez une convention de dénomination cohérente. J'ai préfixé tous les paramètres et variables avec un trait de soulignement
_
, pas seulement quelques . -
Ne pas utiliser la qualification de table dans
EXECUTE
, car il n'y a qu'une seule table impliquée et leEXECUTE
a sa portée distincte. -
J'ai renommé certains paramètres pour clarifier.
_order_by
au lieu de_sort_by
;_order_asc_desc
au lieu de_order
.