C'è spazio per miglioramenti:
CREATE OR REPLACE FUNCTION report_get_countries_new (starts_with text
, ends_with text = NULL)
RETURNS SETOF lookups.countries AS
$func$
DECLARE
sql text := 'SELECT * FROM lookups.countries WHERE country_name >= $1';
BEGIN
IF ends_with IS NOT NULL THEN
sql := sql || ' AND country_name <= $2';
END IF;
RETURN QUERY EXECUTE sql
USING starts_with, ends_with;
END
$func$ LANGUAGE plpgsql;
-- the rest is default settings
Punti principali
-
PostgreSQL 8.4 ha introdotto il
USING
clausola perEXECUTE
, utile per diversi motivi. Riepilogo nel manuale:La stringa di comando può utilizzare valori di parametro, a cui si fa riferimento nel comando come
$1, $2
, ecc. Questi simboli si riferiscono ai valori forniti inUSING
clausola. Questo metodo è spesso preferibile all'inserimento di valori di dati nella stringa di comando come testo:evita il sovraccarico di runtime della conversione dei valori in testo e viceversa ed è molto meno soggetto ad attacchi SQL-injection poiché non è necessario citare o eseguire l'escape.IOW, è più sicuro e veloce rispetto alla creazione di una stringa di query con rappresentazione testuale dei parametri, anche se disinfettata con
quote_literal()
.
Tieni presente che$1, $2
nella stringa di query fare riferimento ai valori forniti inUSING
clausola, non ai parametri della funzione. -
Mentre restituisci
SELECT * FROM lookups.countries
, puoi semplificare ilRETURN
dichiarazione come dimostrato:RETURNS SETOF lookups.countries
In PostgreSQL esiste un tipo composito definito automaticamente per ogni tabella. Usalo. L'effetto è che la funzione dipende dal tipo e viene visualizzato un messaggio di errore se si tenta di modificare la tabella. Rilascia e ricrea la funzione in questo caso.
Questo può o non può essere desiderabile - in genere lo è! Vuoi essere informato degli effetti collaterali se modifichi le tabelle. Così com'è, la tua funzione si interromperà silenziosamente e solleverà un'eccezione alla prossima chiamata.
-
Se fornisci un valore predefinito esplicito per il secondo parametro nella dichiarazione come mostrato, puoi (ma non devi) semplificare la chiamata nel caso in cui non desideri impostare un limite superiore con
ends_with
.SELECT * FROM report_get_countries_new('Zaire');
invece di:
SELECT * FROM report_get_countries_new('Zaire', NULL);
Fai attenzione al sovraccarico delle funzioni in questo contesto.
-
Non citare il nome della lingua
anche se è tollerato (per ora). È un identificatore.'plpgsql' -
È possibile assegnare una variabile al momento della dichiarazione. Risparmia un passaggio in più.
-
I parametri sono nominati nell'intestazione. Elimina le righe senza senso:
starts_with ALIAS FOR $1; ends_with ALIAS FOR $2;