PostgreSQL 函数定义“+ 处或附近的语法错误”

vek*_*tor 2 postgresql functions

假设一个简单的查询:

(SELECT MAX(timestamp) FROM events e WHERE e.id < some_id) 
  + ((SELECT MIN(timestamp) FROM events e WHERE e.id > some_id) 
    - (SELECT MAX(timestamp) FROM events e WHERE e.id < some_id)) / 2
Run Code Online (Sandbox Code Playgroud)

如果 some_id是参数,它会根据某些事件序列找到近似时间戳(它采用前一个和后一个事件并平均它们的时间戳)。

这个查询很好用,现在我想把它打包成一个函数:

CREATE FUNCTION id_to_timestamp(integer) RETURNS timestamp with time zone AS
$BODY$
    (SELECT MAX(timestamp) FROM events e WHERE e.id < $1) 
      + ((SELECT MIN(timestamp) FROM events e WHERE e.id > $1) 
        - (SELECT MAX(timestamp) FROM events e WHERE e.id < $1)) / 2
$BODY$
LANGUAGE sql;
Run Code Online (Sandbox Code Playgroud)

这突然失败并显示消息

ERROR:  syntax error at or near "+"
... events e WHERE e.id < $1) + ((SELECT...
Run Code Online (Sandbox Code Playgroud)

我究竟做错了什么?为什么+运营商有问题?

(实际标识符是匿名的。)

Cra*_*ger 9

一个LANGUAGE sql函数必须是一个完整的 SQL 语句(或多个)。

你的只是一种表达。

只需 prepend SELECT,就像您在独立运行时一样。

$BODY$
SELECT (SELECT ...
Run Code Online (Sandbox Code Playgroud)

它抱怨的原因+是,令人惊讶的是,将顶级查询括起来是合法的。例如,这是一个有效的查询:

regress=> (SELECT 1);
 ?column? 
----------
        1
(1 row)
Run Code Online (Sandbox Code Playgroud)

(在你提出问题之前我也不知道,所以谢谢。我什至不确定这是故意的......)

请注意,如果您按原样运行原始查询,则会遇到相同的错误,因此我假设您已将其添加SELECT到它之前。

regress=> (SELECT 1) + (SELECT 2);
ERROR:  syntax error at or near "+"
LINE 1: (SELECT 1) + (SELECT 2);
Run Code Online (Sandbox Code Playgroud)

  • 我想这是故意的 - 例如,在混合顶级 EXCEPT 和 UNION 时它会有所帮助。 (2认同)