Erklärung
Die Wurzel des Problems ist die unscharfe Definition von „nichts“.
NULL
ist nicht nichts , es ist nur unbekannt, was es genau ist. "Nichts" in Bezug auf SQL wäre keine Zeile :Es wird überhaupt nichts zurückgegeben. Dies geschieht normalerweise, wenn keine Zeile gefunden wird. Aber bei der Verwendung von Aggregatfunktionen , das kann nicht passieren, weil laut Dokumentation:
avg()
gibt NULL
zurück wenn keine Zeilen gefunden werden (also nicht "nichts"). Sie erhalten eine Zeile mit einem NULL
Wert als Ergebnis - der überschreibt Ihren Init-Wert in dem Code, den Sie demonstrieren.
Lösung
Schließen Sie das Ergebnis in COALESCE
ein . Demonstration einer viel einfacheren 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;
Dasselbe kann in einer plpgsql-Funktion verwendet werden. Diese Funktion kann STABLE
sein , kann bei größeren Abfragen die Leistung verbessern.
Andere Fälle
Wenn Sie wirklich können bekomme keine Zeile aus einer Abfrage ein einfaches COALESCE
würde scheitern , weil es nie ausgeführt wird.
Für einen einzelnen Wert Als Ergebnis können Sie die gesamte Abfrage einfach wie folgt umschließen:
SELECT COALESCE((SELECT some_float FROM ... WHERE ... LIMIT 1), 0) AS result
PL/pgSQL hat die Fähigkeit zu prüfen, bevor es tatsächlich von der Funktion zurückkehrt. Dies funktioniert für mehrere Zeilen mit einer oder mehreren Spalten , zu. Es gibt ein Beispiel in das Handbuch
Demonstration der Verwendung von FOUND
:
...
RETURN QUERY SELECT foo, bar ...;
IF NOT FOUND THEN
RETURN QUERY VALUES ('foo_default'::text, 'bar_default'::text);
END IF;
...
Verwandte:
- Datensatz zurückgeben ( virtueller Tisch) aus der Funktion
- PostgreSQL - Überprüfen Sie, ob Fremdschlüssel vorhanden sind, wenn Sie ein SELECT durchführen
Um immer genau eine Zeile zurückzugeben , können Sie auch reines SQL verwenden :
SELECT foo, bar FROM tbl
UNION ALL
SELECT 'foo_default', 'bar_default'
LIMIT 1;
Wenn das erste SELECT
gibt keine Zeile zurück, die zweite SELECT
gibt eine Zeile mit Standardwerten zurück.