Giải thích
Gốc của vấn đề là định nghĩa mờ nhạt của "không phải bất cứ thứ gì".
NULL
không không có gì , nó chỉ không biết chính xác nó là gì. "Không có gì" về mặt SQL sẽ là không có hàng :không có gì được trả lại cả. Điều đó thường xảy ra khi không tìm thấy hàng nào. Nhưng khi sử dụng hàm tổng hợp , điều đó không thể xảy ra vì theo tài liệu:
avg()
trả về NULL
khi không có hàng nào được tìm thấy (vì vậy không phải là "không có gì"). Bạn nhận được một hàng có NULL
giá trị là kết quả - mà ghi đè giá trị init của bạn trong mã bạn chứng minh.
Giải pháp
Kết quả bằng COALESCE
. Trình bày một hàm SQL đơn giản hơn nhiều:
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;
Điều tương tự cũng có thể được sử dụng trong một hàm plpgsql. Hàm này có thể là STABLE
, có thể giúp tăng hiệu suất trong bối cảnh các truy vấn lớn hơn.
Các trường hợp khác
Nếu bạn thực sự có thể không có hàng từ một truy vấn, một COALESCE
đơn giản sẽ thất bại , bởi vì nó không bao giờ được thực thi.
Đối với một giá trị duy nhất kết quả là bạn có thể chỉ gói toàn bộ truy vấn như:
SELECT COALESCE((SELECT some_float FROM ... WHERE ... LIMIT 1), 0) AS result
- Làm cách nào để hiển thị giá trị mặc định khi không tìm thấy kết quả phù hợp nào trong một truy vấn?
PL / pgSQL có khả năng kiểm tra trước khi thực sự quay lại từ hàm. Điều này hoạt động cho nhiều hàng với một hoặc nhiều cột , cũng vậy. Có một ví dụ trong hướng dẫn sử dụng
chứng minh việc sử dụng FOUND
:
...
RETURN QUERY SELECT foo, bar ...;
IF NOT FOUND THEN
RETURN QUERY VALUES ('foo_default'::text, 'bar_default'::text);
END IF;
...
Có liên quan:
- Trả lại bản ghi setof ( bảng ảo) từ chức năng
- PostgreSQL - Kiểm tra khóa ngoại tồn tại khi thực hiện SELECT
Để luôn trả về chính xác một hàng , bạn cũng có thể sử dụng SQL thuần túy :
SELECT foo, bar FROM tbl
UNION ALL
SELECT 'foo_default', 'bar_default'
LIMIT 1;
Nếu SELECT
đầu tiên không trả về hàng nào, SELECT
thứ hai trả về một hàng có giá trị mặc định.