Jeg ville gøre det sådan her:
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$;
Kernefunktion:brug format()
for sikkert og elegant at sammenkæde din forespørgselsstreng. Relateret:
- INDSÆT med dynamisk tabelnavn i triggerfunktion
- Formatspecifikation for heltalsvariabler i format() for EXECUTE?
ASC
/ DESC
(eller ASCENDING
/ DESCENDING
) er faste nøgleord. Jeg tilføjede en manuel kontrol (IF ...
) og senere sammenkæde med en simpel %s
. Det er én måde at hævde juridisk input på. For nemheds skyld tilføjede jeg en fejlmeddelelse for uventet input og en parameterstandard, så funktionen er standard til ASC
hvis den sidste parameter udelades i opkaldet. Relateret:
- Valgfrit argument i PL /pgSQL-funktion
- FEJL:inputparametre efter en med en standardværdi skal også have standardindstillinger i Postgres
Adressering Pavel kommentar
, jeg sammenkæder _limit
og _offset
direkte, så forespørgslen er allerede planlagt med disse parametre.
_limit
og _offset
er integer
parametre, så vi kan bruge almindelig %s
uden fare for SQL-injektion. Du vil måske hævde rimelige værdier (ekskluder negative værdier og værdier for høje), før du sammenkæder ...
-
Brug en konsekvent navnekonvention. Jeg præfiksede alle parametre og variable med en understregning
_
, ikke kun nogle . -
Bruger ikke tabelkvalifikation i
EXECUTE
, da der kun er en enkelt tabel involveret ogEXECUTE
har sit særskilte anvendelsesområde. -
Jeg omdøbte nogle parametre for at præcisere.
_order_by
i stedet for_sort_by
;_order_asc_desc
i stedet for_order
.