PostgreSQL
 sql >> Database >  >> RDS >> PostgreSQL

PostgreSQL:scrittura di SQL dinamico nella procedura memorizzata che restituisce un set di risultati

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 per EXECUTE , 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 in USING 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 in USING clausola, non ai parametri della funzione.

  • Mentre restituisci SELECT * FROM lookups.countries , puoi semplificare il RETURN 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 'plpgsql' anche se è tollerato (per ora). È un identificatore.

  • È 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;