Forklaring
Roden til problemet er den uklare definition af "ikke noget".
NULL
er ikke ingenting , det er bare uvist, hvad det præcist er. "Intet" i form af SQL ville være ingen række :intet returneres overhovedet. Det sker typisk, når der ikke findes nogen række. Men når du bruger samlede funktioner , det kan ikke ske, fordi pr. dokumentation:
avg()
returnerer NULL
når ingen rækker findes (altså ikke "ingenting"). Du får en række med en NULL
værdi som resultat - som overskriver din init-værdi i den kode, du demonstrerer.
Løsning
Pak resultatet ind i COALESCE
. Demonstrerer en meget enklere SQL-funktion:
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;
Det samme kan bruges i en plpgsql-funktion. Denne funktion kan være STABLE
, kan hjælpe med ydeevne i forbindelse med større forespørgsler.
Andre sager
Hvis du faktisk kan få ingen række fra en forespørgsel, en simpel COALESCE
ville mislykkes , fordi det aldrig bliver udført.
For en enkelt værdi resultat kan du bare pakke hele forespørgslen som:
SELECT COALESCE((SELECT some_float FROM ... WHERE ... LIMIT 1), 0) AS result
PL/pgSQL har mulighed for at tjekke, før du rent faktisk vender tilbage fra funktionen. Dette virker for flere rækker med en eller flere kolonner , også. Der er et eksempel i manualen
demonstrerer brugen af FOUND
:
...
RETURN QUERY SELECT foo, bar ...;
IF NOT FOUND THEN
RETURN QUERY VALUES ('foo_default'::text, 'bar_default'::text);
END IF;
...
Relateret:
- Return sæt af post ( virtuel tabel) fra funktion
- PostgreSQL - Kontroller, at fremmednøgle findes, når du laver en SELECT
For altid at returnere præcis én række , kan du også bruge ren SQL :
SELECT foo, bar FROM tbl
UNION ALL
SELECT 'foo_default', 'bar_default'
LIMIT 1;
Hvis den første SELECT
returnerer ingen række, den anden SELECT
returnerer en række med standardindstillinger.