Ich würde es so machen:
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$;
Kernfunktion:Verwenden Sie das Format format()
um Ihre Abfragezeichenfolge sicher und elegant zu verketten. Verwandte:
- INSERT with dynamischer Tabellenname in Triggerfunktion
- Formatbezeichner für Integer-Variablen in format() für EXECUTE?
ASC
/ DESC
(oder ASCENDING
/ DESCENDING
) sind feste Schlüsselwörter. Ich habe eine manuelle Prüfung hinzugefügt (IF ...
) und später mit einem einfachen %s
verketten . Das ist eins Möglichkeit zur Geltendmachung von Rechtsansprüchen. Der Einfachheit halber habe ich eine Fehlermeldung für unerwartete Eingaben und einen Parameterstandard hinzugefügt, sodass die Funktion standardmäßig auf ASC
gesetzt wird wenn beim Aufruf der letzte Parameter weggelassen wird. Verwandte:
- Optionales Argument in PL /pgSQL-Funktion
- FEHLER:Eingabeparameter nach einem mit einem Standardwert müssen auch Standardwerte in Postgres haben
Die Adressierung von Pavel ist gültig Kommentar
, verkette ich _limit
und _offset
direkt, sodass die Abfrage bereits mit diesen Parametern geplant ist.
_limit
und _offset
sind integer
Parameter, sodass wir einfach %s
verwenden können ohne die Gefahr einer SQL-Injection. Möglicherweise möchten Sie vernünftige Werte geltend machen (negative Werte und zu hohe Werte ausschließen), bevor Sie ...
-
Verwenden Sie eine konsistente Namenskonvention. Ich habe allen Parametern und Variablen einen Unterstrich
_
vorangestellt , nicht nur einige . -
Keine Tabellenqualifizierung in
EXECUTE
verwenden , da es sich nur um eine einzige Tabelle handelt und dieEXECUTE
hat einen separaten Geltungsbereich. -
Zur Verdeutlichung habe ich einige Parameter umbenannt.
_order_by
statt_sort_by
;_order_asc_desc
statt_order
.