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

Come restituire un valore da una funzione se non viene trovato alcun valore

Spiegazione

La radice del problema è la definizione confusa di "non niente".

NULL non è niente , non si sa cosa sia esattamente. "Niente" in termini di SQL sarebbe nessuna riga :non viene restituito nulla. Ciò accade in genere quando non viene trovata alcuna riga. Ma quando si utilizzano funzioni di aggregazione , ciò non può accadere perché, per documentazione:

avg() restituisce NULL quando non vengono trovate righe (quindi non "niente"). Ottieni una riga con un NULL valore come risultato - che sovrascrive il tuo valore init nel codice che mostri.

Soluzione

Racchiudi il risultato in COALESCE . Dimostrazione di una funzione SQL molto più semplice:

CREATE OR REPLACE FUNCTION get_height_sql(firstn varchar, lastn varchar)
  RETURNS float AS
$func$
   SELECT COALESCE(AVG(((p.h_feet * 12) + p.h_inches) * 2.54)::float, 0)
   FROM   player p
   WHERE  p.firstname = firstn
   AND    p.lastname = lastn
$func$  LANGUAGE sql STABLE;

SQL Fiddle.

Lo stesso può essere utilizzato in una funzione plpgsql. Questa funzione può essere STABLE , potrebbe aiutare con le prestazioni nel contesto di query più grandi.

Altri casi

Se davvero puoi ottenere nessuna riga da una query, un semplice COALESCE fallirebbe , perché non viene mai eseguito.

Per un valore unico risultato puoi semplicemente avvolgere l'intera query come:

SELECT COALESCE((SELECT some_float FROM ... WHERE ... LIMIT 1), 0) AS result

PL/pgSQL ha la capacità di controllare prima di tornare effettivamente dalla funzione. Funziona per più righe con una o più colonne , anche. C'è un esempio in il manuale dimostrando l'uso di FOUND :

...
RETURN QUERY SELECT foo, bar ...;

IF NOT FOUND THEN
    RETURN QUERY VALUES ('foo_default'::text, 'bar_default'::text);
END IF;
...

Correlati:

Per restituire sempre esattamente una riga , puoi anche utilizzare SQL puro :

SELECT foo, bar FROM tbl
UNION ALL
SELECT 'foo_default', 'bar_default'
LIMIT 1;

Se il primo SELECT non restituisce nessuna riga, la seconda SELECT restituisce una riga con valori predefiniti.