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;
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
- Come visualizzare un valore predefinito quando non viene trovata alcuna corrispondenza in una query?
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:
- Restituisci setof record ( tabella virtuale) dalla funzione
- PostgreSQL:verifica che la chiave esterna esista quando esegui un SELECT
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.