Explication
La racine du problème est la définition floue de "pas n'importe quoi".
NULL
n'est pas rien , on ne sait pas ce que c'est exactement. "Rien" en termes de SQL serait aucune ligne :rien n'est retourné du tout. Cela se produit généralement lorsqu'aucune ligne n'est trouvée. Mais lors de l'utilisation de fonctions d'agrégation , cela ne peut pas arriver car, par documentation :
avg()
renvoie NULL
lorsqu'aucune ligne n'est trouvée (donc pas "rien"). Vous obtenez une ligne avec un NULL
valeur comme résultat - qui écrase votre valeur init dans le code que vous démontrez.
Solution
Enveloppez le résultat dans COALESCE
. Démonstration d'une fonction SQL beaucoup plus simple :
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;
La même chose peut être utilisée dans une fonction plpgsql. Cette fonction peut être STABLE
, peut améliorer les performances dans le contexte de requêtes plus volumineuses.
Autres cas
Si vous pouvez réellement obtenir aucune ligne à partir d'une requête, un simple COALESCE
échouerait , car il n'est jamais exécuté.
Pour une valeur unique résultat, vous pouvez simplement envelopper toute la requête comme :
SELECT COALESCE((SELECT some_float FROM ... WHERE ... LIMIT 1), 0) AS result
- Comment afficher une valeur par défaut lorsqu'aucune correspondance n'est trouvée dans une requête ?
PL/pgSQL a la capacité de vérifier avant de réellement revenir de la fonction. Cela fonctionne pour plusieurs lignes avec une ou plusieurs colonnes , aussi. Il existe un exemple dans le manuel
démontrant l'utilisation de FOUND
:
...
RETURN QUERY SELECT foo, bar ...;
IF NOT FOUND THEN
RETURN QUERY VALUES ('foo_default'::text, 'bar_default'::text);
END IF;
...
Connexe :
- Renvoyer l'ensemble d'enregistrements ( table virtuelle) de la fonction
- PostgreSQL - Vérifier que la clé étrangère existe lors d'un SELECT
Pour toujours renvoyer exactement une ligne , vous pouvez également utiliser SQL pur :
SELECT foo, bar FROM tbl
UNION ALL
SELECT 'foo_default', 'bar_default'
LIMIT 1;
Si le premier SELECT
ne renvoie aucune ligne, la seconde SELECT
renvoie une ligne avec les valeurs par défaut.