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 deEXECUTEheeft zijn eigen bereik. -
Ik heb een aantal parameters hernoemd ter verduidelijking.
_order_byin plaats van_sort_by;_order_asc_descin plaats van_order.