Lo farei così:
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$;
Funzionalità principale:usa format()
per concatenare in modo sicuro ed elegante la stringa di query. Correlati:
- INSERIRE con nome della tabella dinamica nella funzione trigger
- Identificatore di formato per variabili intere in format() per EXECUTE?
ASC
/ DESC
(o ASCENDING
/ DESCENDING
) sono parole chiave fisse. Ho aggiunto un controllo manuale (IF ...
) e successivamente concatenare con un semplice %s
. Questo è uno modo per far valere un contributo legale. Per comodità, ho aggiunto un messaggio di errore per input imprevisto e un parametro predefinito, quindi la funzione è impostata su ASC
se l'ultimo parametro viene omesso nella chiamata. Correlati:
- Argomento facoltativo in PL /pgSQL funzione
- ERRORE:i parametri di input dopo uno con un valore predefinito devono avere valori predefiniti anche in Postgres
Indirizzamento Pavel è valido commenta
, concateno _limit
e _offset
direttamente, quindi la query è già pianificata con quei parametri.
_limit
e _offset
sono integer
parametri, quindi possiamo usare un semplice %s
senza il pericolo di SQL injection. Potresti voler affermare valori ragionevoli (escludere valori negativi e valori troppo alti) prima di concatenare ...
-
Usa una convenzione di denominazione coerente. Ho prefissato tutti i parametri e le variabili con un trattino basso
_
, non solo alcuni . -
Non utilizza la qualificazione della tabella all'interno di
EXECUTE
, poiché è coinvolta solo una singola tabella eEXECUTE
ha un ambito separato. -
Ho rinominato alcuni parametri per chiarire.
_order_by
invece di_sort_by
;_order_asc_desc
invece di_order
.