Förklaring
Roten till problemet är den flummiga definitionen av "inte någonting".
NULL
är inte ingenting , det är bara okänt vad det är exakt. "Ingenting" i termer av SQL skulle vara ingen rad :inget returneras alls. Det händer vanligtvis när ingen rad hittas. Men när du använder aggregatfunktioner , det kan inte hända eftersom per dokumentation:
avg()
returnerar NULL
när inga rader hittas (alltså inte "ingenting"). Du får en rad med en NULL
värde som resultat - som skriver över ditt init-värde i koden du visar.
Lösning
Slå in resultatet i COALESCE
. Demonstrerar en mycket enklare 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;
Detsamma kan användas i en plpgsql-funktion. Denna funktion kan vara STABLE
, kan hjälpa till med prestanda i samband med större frågor.
Övriga fall
Om du verkligen kan få ingen rad från en fråga, en enkel COALESCE
skulle misslyckas , eftersom det aldrig körs.
För ett enda värde resultatet kan du bara slå in hela frågan så här:
SELECT COALESCE((SELECT some_float FROM ... WHERE ... LIMIT 1), 0) AS result
PL/pgSQL har möjlighet att kontrollera innan du faktiskt återvänder från funktionen. Detta fungerar för flera rader med en eller flera kolumner också. Det finns ett exempel i handboken
demonstrerar användningen av FOUND
:
...
RETURN QUERY SELECT foo, bar ...;
IF NOT FOUND THEN
RETURN QUERY VALUES ('foo_default'::text, 'bar_default'::text);
END IF;
...
Relaterat:
- Returnera uppsättning av post ( virtuell tabell) från funktion
- PostgreSQL - Kontrollera att främmande nyckel finns när du gör en SELECT
Att alltid returnera exakt en rad , kan du också använda ren SQL :
SELECT foo, bar FROM tbl
UNION ALL
SELECT 'foo_default', 'bar_default'
LIMIT 1;
Om den första SELECT
returnerar ingen rad, den andra SELECT
returnerar en rad med standardvärden.