如果未找到值,如何 return 来自函数的值
How to return a value from a function if no value is found
我正在尝试 return 0.0
如果以下函数没有 return 任何东西:
CREATE OR REPLACE FUNCTION get_height(firstn VARCHAR, lastn VARCHAR)
RETURNS FLOAT AS
$$
DECLARE
height FLOAT = 0.0;
BEGIN
SELECT into height AVG(((p.h_feet * 12) + p.h_inches) * 2.54)
FROM player p
WHERE p.firstname = firstn AND p.lastname = lastn;
RETURN height;
END;
$$ LANGUAGE plpgsql;
我尝试搜索它,发现 COALESCE
不起作用。有人知道如何解决这个问题吗?
Table结构:
create table player(
firstname text
,lastname text
,h_feet INT
,h_inches INT
);
示例数据:
insert into player values ('Jimmy','Howard',6,2);
return coalesce(height, 0::decimal(10,2));
应该可以解决问题
这是我使用的脚本。如您所见,我 运行 PostgreSQL 9.4.1。
我使用 HeidiSQL 来启动查询。
你确定你正确地更新了你的功能吗?
我刚刚注意到您在评论中使用了不同的函数 ('player_height') 而不是原始 post 中的 'get_height'。
select version();
-- PostgreSQL 9.4.1, compiled by Visual C++ build 1800, 64-bit
delimiter //
CREATE OR REPLACE FUNCTION get_height(firstn VARCHAR, lastn VARCHAR)
RETURNS FLOAT AS $$
DECLARE
height FLOAT = 0.0;
BEGIN
SELECT into height AVG(((p.h_feet * 12) + p.h_inches) * 2.54)
FROM players p
WHERE p.firstname = firstn AND p.lastname = lastn;
return coalesce(height, 0.0);
END;
$$ LANGUAGE plpgsql;
delimiter;
CREATE TABLE players (
firstname varchar(40),
lastname varchar(40),
h_feet int,
h_inches int);
insert into players values ('Jimmy', 'Howard', 6, 2);
select * from get_height('Jimmy', 'Howard');
-- gives 187.96
select * from get_height('Random', 'Guy');
-- gives 0
说明
问题的根源在于"not anything"的模糊定义。
if the following function does not return anything
NULL
不是什么,只是不知道它到底是什么。 "Nothing" 就 SQL 而言将是 无行 :根本没有 returned。当找不到行时通常会发生这种情况。但是当使用 聚合函数 时,这不会发生,因为 per documentation:
... these functions return a null value when no rows are selected.
avg()
returns NULL
当没有找到行时(所以不是 "nothing")。作为结果,您得到一行带有 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
- How to display a default value when no match found in a query?
PL/pgSQL 能够在实际 return 从函数中进行检查之前进行检查。这也适用于具有一列或多列的多行。有一个 example in the manual 演示了 FOUND
:
的用法
...
RETURN QUERY SELECT foo, bar ...;
IF NOT FOUND THEN
RETURN QUERY VALUES ('foo_default'::text, 'bar_default'::text);
END IF;
...
相关:
- Return setof record (virtual table) from function
- PostgreSQL - Check foreign key exists when doing a SELECT
要始终return恰好一行,您还可以使用纯SQL:
SELECT foo, bar FROM tbl
UNION ALL
SELECT 'foo_default', 'bar_default'
LIMIT 1;
如果第一个 SELECT
return 没有行,第二个 SELECT
return 有默认行。
尝试not found
条件
SELECT ... into ...
FROM ...
WHERE ...;
if not found then
RETURN 0;
end if;
我正在尝试 return 0.0
如果以下函数没有 return 任何东西:
CREATE OR REPLACE FUNCTION get_height(firstn VARCHAR, lastn VARCHAR)
RETURNS FLOAT AS
$$
DECLARE
height FLOAT = 0.0;
BEGIN
SELECT into height AVG(((p.h_feet * 12) + p.h_inches) * 2.54)
FROM player p
WHERE p.firstname = firstn AND p.lastname = lastn;
RETURN height;
END;
$$ LANGUAGE plpgsql;
我尝试搜索它,发现 COALESCE
不起作用。有人知道如何解决这个问题吗?
Table结构:
create table player(
firstname text
,lastname text
,h_feet INT
,h_inches INT
);
示例数据:
insert into player values ('Jimmy','Howard',6,2);
return coalesce(height, 0::decimal(10,2));
应该可以解决问题
这是我使用的脚本。如您所见,我 运行 PostgreSQL 9.4.1。 我使用 HeidiSQL 来启动查询。 你确定你正确地更新了你的功能吗? 我刚刚注意到您在评论中使用了不同的函数 ('player_height') 而不是原始 post 中的 'get_height'。
select version();
-- PostgreSQL 9.4.1, compiled by Visual C++ build 1800, 64-bit
delimiter //
CREATE OR REPLACE FUNCTION get_height(firstn VARCHAR, lastn VARCHAR)
RETURNS FLOAT AS $$
DECLARE
height FLOAT = 0.0;
BEGIN
SELECT into height AVG(((p.h_feet * 12) + p.h_inches) * 2.54)
FROM players p
WHERE p.firstname = firstn AND p.lastname = lastn;
return coalesce(height, 0.0);
END;
$$ LANGUAGE plpgsql;
delimiter;
CREATE TABLE players (
firstname varchar(40),
lastname varchar(40),
h_feet int,
h_inches int);
insert into players values ('Jimmy', 'Howard', 6, 2);
select * from get_height('Jimmy', 'Howard');
-- gives 187.96
select * from get_height('Random', 'Guy');
-- gives 0
说明
问题的根源在于"not anything"的模糊定义。
if the following function does not return anything
NULL
不是什么,只是不知道它到底是什么。 "Nothing" 就 SQL 而言将是 无行 :根本没有 returned。当找不到行时通常会发生这种情况。但是当使用 聚合函数 时,这不会发生,因为 per documentation:
... these functions return a null value when no rows are selected.
avg()
returns NULL
当没有找到行时(所以不是 "nothing")。作为结果,您得到一行带有 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
- How to display a default value when no match found in a query?
PL/pgSQL 能够在实际 return 从函数中进行检查之前进行检查。这也适用于具有一列或多列的多行。有一个 example in the manual 演示了 FOUND
:
...
RETURN QUERY SELECT foo, bar ...;
IF NOT FOUND THEN
RETURN QUERY VALUES ('foo_default'::text, 'bar_default'::text);
END IF;
...
相关:
- Return setof record (virtual table) from function
- PostgreSQL - Check foreign key exists when doing a SELECT
要始终return恰好一行,您还可以使用纯SQL:
SELECT foo, bar FROM tbl
UNION ALL
SELECT 'foo_default', 'bar_default'
LIMIT 1;
如果第一个 SELECT
return 没有行,第二个 SELECT
return 有默认行。
尝试not found
条件
SELECT ... into ...
FROM ...
WHERE ...;
if not found then
RETURN 0;
end if;