Обяснение
Коренът на проблема е размитата дефиниция на „нищо“.
NULL
не е нищо , само не се знае какво точно е. „Нищо“ от гледна точка на SQL би било няма ред :не се връща нищо. Това обикновено се случва, когато не е намерен ред. Но когато използвате агрегирани функции , това не може да се случи, защото по документация:
avg()
връща NULL
когато не са намерени редове (така че не "нищо"). Получавате ред с NULL
стойност като резултат - която заменя вашата начална стойност в кода, който демонстрирате.
Решение
Обвийте резултата в COALESCE
. Демонстриране на много по-проста SQL функция:
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;
Същото може да се използва във функция plpgsql. Тази функция може да бъде STABLE
, може да помогне с производителността в контекста на по-големи заявки.
Други случаи
Ако наистина можете вземете без ред от заявка, просто COALESCE
ще се провали , защото никога не се изпълнява.
За единствена стойност в резултат можете просто да обвиете цялата заявка като:
SELECT COALESCE((SELECT some_float FROM ... WHERE ... LIMIT 1), 0) AS result
PL/pgSQL има способността да проверява, преди действително да се върне от функцията. Това работи за няколко реда с една или повече колони , също. Има пример в ръководството
демонстриране на използването на FOUND
:
...
RETURN QUERY SELECT foo, bar ...;
IF NOT FOUND THEN
RETURN QUERY VALUES ('foo_default'::text, 'bar_default'::text);
END IF;
...
Свързани:
- Върнете setof запис ( виртуална таблица) от функция
- PostgreSQL - Проверете съществуването на външен ключ, когато правите SELECT
Винаги да връщате точно един ред , можете също да използвате чист SQL :
SELECT foo, bar FROM tbl
UNION ALL
SELECT 'foo_default', 'bar_default'
LIMIT 1;
Ако първият SELECT
не връща ред, вторият SELECT
връща ред със стойности по подразбиране.