Greenplum plpgsql 函数在输入结束时返回语法错误
Posted
技术标签:
【中文标题】Greenplum plpgsql 函数在输入结束时返回语法错误【英文标题】:Greenplum plpgsql function returns syntax error at end of input 【发布时间】:2016-05-20 08:12:53 【问题描述】:我在 Greenplum 中编写了一个 PL/pgSQL 函数,该函数需要将 interval
其中 < interval '00:00:00'
转换为正值。
例如,间隔值-23:57:00
应转换为00:03:00
。所以我写了这个函数:
CREATE OR REPLACE FUNCTION abstime(timeval INTERVAL)
RETURNS INTERVAL AS $$
BEGIN
IF timeval < INTERVAL '00:00:00' THEN
RETURN timeval + INTERVAL '24:00:00';
ELSE
RETURN timeval;
END IF;
RETURN;
END;
$$ LANGUAGE plpgsql;
我进入后得到:
ERROR: syntax error at end of input LINE 1: SELECT ^ QUERY: SELECT CONTEXT: SQL statement in PL/PgSQL function "abstime" near line 7
我不知道出了什么问题?
【问题讨论】:
我猜这个错误是在调用函数后出现的。向我们展示该调用。 你有多少abstime
函数?..
其实我根本没有调用这个函数,按下enter
后出现这个错误,所以我的\df
中根本没有任何函数
【参考方案1】:
现代 PostgreSQL 有更好的诊断:
postgres=# CREATE OR REPLACE FUNCTION abstime(timeval INTERVAL)
RETURNS INTERVAL AS $$
BEGIN
IF timeval < INTERVAL '00:00:00' THEN
RETURN timeval + INTERVAL '24:00:00';
ELSE
RETURN timeval;
END IF;
RETURN; --- SHOULD BE REMOVED
END;
$$ LANGUAGE plpgsql;
ERROR: missing expression at or near ";"
LINE 9: RETURN;
^
第 9 行的 return 是无用的,并且缺少一个表达式。您必须删除第 9 行。在这种情况下,RETURN
语句中需要表达式。
【讨论】:
是的,非常感谢。return;
的东西是从教程中得到的,我使用的是 greenplum
,它基于 postgresql v8.2
。【参考方案2】:
Pavel 在如何修复函数方面是 100% 正确的,但基于函数代码,并且因为您使用的是 Greenplum,我猜您想针对大表选择此内联。这样做时,您需要避免 PL/pgSQL 的开销。它是一门很棒的语言,我经常使用它,但我会避免将它用于内联 SQL。使用 PL/pgSQL 封装转换逻辑,而不是内联 SQL。
其次,我会将函数设为 IMMUTABLE,因为您没有在函数中更新数据库,并且对于给定的参数总是返回相同的值。更多关于这里: http://www.postgresql.org/docs/8.2/static/xfunc-volatility.html
证明:
CREATE OR REPLACE FUNCTION abstime(timeval INTERVAL)
RETURNS INTERVAL AS $$
BEGIN
IF timeval < INTERVAL '00:00:00' THEN
RETURN timeval + INTERVAL '24:00:00';
ELSE
RETURN timeval;
END IF;
END;
$$ LANGUAGE plpgsql;
现在得到解释计划。
EXPLAIN ANALYZE SELECT abstime('04:00:00'::interval);
Result (cost=0.01..0.02 rows=1 width=0)
Rows out: 1 rows with 5.230 ms to end, start offset by 0.124 ms.
InitPlan
-> Result (cost=0.00..0.01 rows=1 width=0)
Rows out: 1 rows with 5.146 ms to end of 2 scans, start offset by 0.130 ms.
Slice statistics:
(slice0) Executor memory: 63K bytes.
(slice1) Executor memory: 37K bytes.
Statement statistics:
Memory used: 128000K bytes
Settings: optimizer=on
Optimizer status: legacy query optimizer
Total runtime: 5.356 ms
现在,将此函数重写为 SQL 函数并使用 IMMUTABLE 标志。
CREATE OR REPLACE FUNCTION abstime_v2(timeval INTERVAL)
RETURNS INTERVAL AS
$$
SELECT CASE WHEN $1 < INTERVAL '00:00:00' THEN $1 + INTERVAL '24:00:00' ELSE $1 END;
$$
LANGUAGE sql IMMUTABLE;
解释计划。
EXPLAIN ANALYZE SELECT abstime_v2('04:00:00'::interval);
Result (cost=0.00..0.00 rows=1 width=16)
Rows out: 1 rows with 0.002 ms to end, start offset by 0.042 ms.
-> Result (cost=0.00..0.00 rows=1 width=1)
Rows out: 1 rows with 0.001 ms to end, start offset by 0.043 ms.
Slice statistics:
(slice0) Executor memory: 13K bytes.
Statement statistics:
Memory used: 128000K bytes
Settings: optimizer=on
Optimizer status: PQO version 1.607
Total runtime: 0.046 ms
v2 功能所需的扫描和内存更少。
【讨论】:
哦,是的,这真的很有帮助,是的,因为我使用的是Greenplum,所以我应该考虑资源成本。以上是关于Greenplum plpgsql 函数在输入结束时返回语法错误的主要内容,如果未能解决你的问题,请参考以下文章