Ik zou het als volgt doen:
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$;
Kernfunctie:gebruik de indeling format()
om uw queryreeks veilig en elegant samen te voegen. Gerelateerd:
- INSERT met dynamische tabelnaam in triggerfunctie
- Formaatspecificatie voor integer-variabelen in format() voor EXECUTE?
ASC
/ DESC
(of ASCENDING
/ DESCENDING
) zijn vaste trefwoorden. Ik heb een handmatige controle toegevoegd (IF ...
) en later samenvoegen met een eenvoudige %s
. Dat is één manier om juridische inbreng te doen gelden. Voor het gemak heb ik een foutmelding toegevoegd voor onverwachte invoer en een parameterstandaard, zodat de functie standaard is ingesteld op ASC
als de laatste parameter wordt weggelaten in de aanroep. Gerelateerd:
- Optioneel argument in PL /pgSQL-functie
- FOUT:invoerparameters na één met een standaardwaarde moeten ook standaardwaarden hebben in Postgres
Adressering van Pavel is geldig commentaar
, ik voeg _limit
samen en _offset
direct, dus de query is al gepland met die parameters.
_limit
en _offset
zijn integer
parameters, zodat we gewone %s
. kunnen gebruiken zonder het gevaar van SQL-injectie. Misschien wilt u redelijke waarden claimen (exclusief negatieve waarden en waarden die te hoog zijn) voordat u samenvoegt ...
-
Gebruik een consistente naamgevingsconventie. Ik heb alle parameters en variabelen voorafgegaan door een onderstrepingsteken
_
, niet alleen sommige . -
Tabelkwalificatie niet gebruiken binnen
EXECUTE
, aangezien er maar één tabel bij betrokken is en deEXECUTE
heeft zijn eigen bereik. -
Ik heb een aantal parameters hernoemd ter verduidelijking.
_order_by
in plaats van_sort_by
;_order_asc_desc
in plaats van_order
.