设置Postgres函数的默认返回值

时间:2011-10-05 14:16:13

标签: sql function postgresql if-statement plpgsql

我在Postgres中有以下功能:

CREATE OR REPLACE FUNCTION point_total(user_id integer, gametime date)
  RETURNS bigint AS
$BODY$
SELECT sum(points) AS result
  FROM picks
 WHERE user_id = $1
   AND picks.gametime > $2
   AND points IS NOT NULL;
$BODY$
  LANGUAGE sql VOLATILE; 

它工作正常,但是当用户启动并且没有点时,它会非常合理地返回NULL。如何修改它以使其返回0。

将函数体更改为以下情况会导致“错误:语法错误处于或接近”IF“。

SELECT sum(points) AS result
  FROM picks
 WHERE user_id = $1
   AND picks.gametime > $2
   AND points IS NOT NULL;

IF result IS NULL
   SELECT 0 AS result;
END;

1 个答案:

答案 0 :(得分:10)

如果要使用PL / pgSQL的过程功能,则需要将语言从sql更改为plpgsql。功能体也会改变。

请注意所有参数名称在函数体中都可见,包括所有级别的SQL语句。如果您创建命名冲突,则可能需要对列名进行表格限定,如下所示:table.col,以避免混淆。由于你无论如何通过位置引用($n)引用函数参数,我只是删除了参数名称以使其工作。

最后,THEN声明中缺少IF - 错误消息的直接原因

可以使用COALESCE替换NULL值。但这仅在至少有一个结果行时才有效。 COALESCE无法修复“无行”,只能替换实际的NULL值。

有几种方法可以涵盖所有NULL个案例。在 plpgsql函数

CREATE OR REPLACE FUNCTION point_total(integer, date, OUT result bigint)
  RETURNS bigint AS
$func$
BEGIN

SELECT sum(p.points)          -- COALESCE would make sense ...
INTO   result
FROM   picks p
WHERE  p.user_id = $1
AND    p.gametime > $2
AND    p.points IS NOT NULL;  -- ... if NULL values were not ruled out

IF NOT FOUND THEN             -- If no row was found ...
   result := 0;               -- ... set to 0 explicitly
END IF;

END
$func$  LANGUAGE plpgsql;

或者您可以将整个查询括在外COALESCE的{​​{1}}表达式中。内部SELECT中的“无行”会在表达式中生成SELECT。作为普通SQL工作,或者您可以将其包装在 sql函数

NULL

相关答案:

关于命名冲突

最有可能是命名冲突。 版本9.0 发生了重大变化。我引用release notes

  

E.8.2.5。 PL / pgSQL的

     

如果变量名与a冲突,PL / pgSQL现在会抛出错误   查询中使用的列名(Tom Lane)

后来的版本改进了这种行为。在明显的位置,自动选择正确的选择。减少冲突的可能性,但它仍然存在。该建议仍适用于Postgres 9.3。