Penjelasan
Akar masalahnya adalah definisi kabur dari "bukan apa-apa".
NULL
bukan apa-apa , itu hanya tidak diketahui apa itu sebenarnya. "Tidak ada" dalam istilah SQL akan menjadi tidak ada baris :tidak ada yang dikembalikan sama sekali. Itu biasanya terjadi ketika tidak ada baris yang ditemukan. Namun saat menggunakan fungsi agregat , itu tidak dapat terjadi karena, per dokumentasi:
avg()
mengembalikan NULL
ketika tidak ada baris yang ditemukan (jadi bukan "tidak ada"). Anda mendapatkan baris dengan NULL
nilai sebagai hasil - yang ditimpa nilai init Anda dalam kode yang Anda tunjukkan.
Solusi
Bungkus hasilnya dalam COALESCE
. Mendemonstrasikan fungsi SQL yang lebih sederhana:
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;
Hal yang sama dapat digunakan dalam fungsi plpgsql. Fungsi ini dapat menjadi STABLE
, mungkin membantu performa dalam konteks kueri yang lebih besar.
Kasus lain
Jika Anda benar-benar bisa dapatkan tanpa baris dari kueri, COALESCE
simple sederhana akan gagal , karena tidak pernah dieksekusi.
Untuk nilai tunggal hasilnya Anda bisa membungkus seluruh kueri seperti:
SELECT COALESCE((SELECT some_float FROM ... WHERE ... LIMIT 1), 0) AS result
PL/pgSQL memiliki kemampuan untuk memeriksa sebelum benar-benar kembali dari fungsi. Ini berfungsi untuk beberapa baris dengan satu atau beberapa kolom , juga. Ada contoh di panduan
mendemonstrasikan penggunaan FOUND
:
...
RETURN QUERY SELECT foo, bar ...;
IF NOT FOUND THEN
RETURN QUERY VALUES ('foo_default'::text, 'bar_default'::text);
END IF;
...
Terkait:
- Kembalikan kumpulan catatan ( tabel virtual) dari fungsi
- PostgreSQL - Periksa kunci asing yang ada saat melakukan SELECT
Untuk selalu mengembalikan tepat satu baris , Anda juga dapat menggunakan SQL murni :
SELECT foo, bar FROM tbl
UNION ALL
SELECT 'foo_default', 'bar_default'
LIMIT 1;
Jika SELECT
pertama tidak mengembalikan baris, SELECT
second kedua mengembalikan baris dengan default.