Postgresql Postgres函数始终返回一行

Postgresql Postgres函数始终返回一行,postgresql,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

我在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;
有趣的是: 如果我将返回类型从“用户”更改为
表格(“Email”文本、“GivenName”文本、“ID”int8、“Password”文本、“Salt”文本)

它按预期工作。 但我真的想用“引用”来表示“用户”,因为维护会更容易


谢谢

这是一个标量函数,因此每次都必须返回值。您可能需要一个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函数,在查询表达式中使用标量函数:

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子句更改为返回“User”集合

您需要将返回类型从“User”更改为“User”集合。如果是单列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;

请注意-从性能角度来看,对于这些琐碎的功能,使用plpgsql是不好的。由于外部查询的内联,SQL通常会大大加快。其他注意事项-如果必须使用plpgsql-则可以将示例简化为一条语句-`RETURN query。。。