Postgres函数总是返回一行

时间:2015-05-10 14:43:34

标签: postgresql

我在Postgres中编写了以下函数,但是我遇到了一个问题:它总是返回一行。我的意思是,当没有用户匹配该对时,它返回一行,所有列都为空。

如果没有结果,有没有办法让函数返回0(零)行?

CREATE OR REPLACE FUNCTION find_user_by_credentials(email text, password text)
RETURNS
"User"
AS
$$
    SELECT *
        FROM "User" AS "U"
    WHERE email = "U"."Email" AND "U"."Password" = md5(password || "U"."Salt")
    ;
$$
LANGUAGE SQL IMMUTABLE STRICT;

有趣: 如果我从"用户"更改返回类型至 TABLE("Email" text,"GivenName" text,"ID" int8, "Password" text,"Salt" text)

它按预期工作。 但我真的想要使用"参考"用户"用户"因为维护会更容易。

谢谢!

2 个答案:

答案 0 :(得分:4)

这是一个标量函数,因此每次都必须返回值。您可能需要SRF功能,设置返回功能:

CREATE OR REPLACE FUNCTION public.foo(boolean)
 RETURNS integer
 LANGUAGE sql
 AS $function$
  SELECT * FROM generate_series(1,2) WHERE $1;
 $function$

CREATE OR REPLACE FUNCTION public.srf_foo(boolean)
 RETURNS SETOF integer
 LANGUAGE sql
 AS $function$
  SELECT * FROM generate_series(1,2) WHERE $1;
 $function$

postgres=# \pset null [NULL]
Null display is "[NULL]".
postgres=# SELECT * FROM foo(false);
┌────────┐
│  foo   │
╞════════╡
│ [NULL] │
└────────┘
(1 row)

postgres=# SELECT * FROM srf_foo(false);
┌─────────┐
│ srf_foo │
╞═════════╡
└─────────┘
(0 rows)

这可能有点奇怪,因为PostgreSQL在标量函数和SRF函数之间存在差异,但允许使用SRF作为标量和标量作为SRF(但最好在FROM子句中使用SRF函数,并在查询表达式中使用标量函数:< / p>

postgres=# SELECT srf_foo(false);
┌─────────┐
│ srf_foo │
╞═════════╡
└─────────┘
(0 rows)

postgres=# SELECT foo(false);
┌────────┐
│  foo   │
╞════════╡
│ [NULL] │
└────────┘
(1 row)

你可以看到,SRF功能正在运行:

postgres=# SELECT * FROM srf_foo(true);
┌─────────┐
│ srf_foo │
╞═════════╡
│       1 │
│       2 │
└─────────┘
(2 rows)

对于您的示例 - 只需将return子句更改为RETURNS SETOF "User"

答案 1 :(得分:2)

您需要更改&#34; user&#34;的返回类型到SETOF&#34;用户&#34;。在单行rowtype的情况下,函数将始终产生一行 - 有或没有值,而使用SETOF将允许返回由零行或多行组成的集合。我还将函数的语言从SQL更改为PLPGSQL:

CREATE OR REPLACE FUNCTION find_user_by_credentials(email text, password text)
RETURNS SETOF "user" AS $$
DECLARE
  user_row RECORD;
BEGIN
  SELECT INTO user_row *
  FROM "user" AS "U"
  WHERE "U".email = "U"."email"
  AND "U"."password" = md5("U"."password" || "U"."salt");
  IF FOUND THEN
    RETURN NEXT user_row;
  END IF;
  RETURN;
END;
$$
LANGUAGE plpgsql VOLATILE;