Greenplum plpgsql 函数 returns 输入末尾的语法错误
Greenplum plpgsql function returns syntax error at end of input
我在 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
我不确定出了什么问题?
现代 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
语句中需要表达式。
Pavel 关于如何修复该函数是 100% 正确的,但基于函数代码并且因为您使用的是 Greenplum,我猜您想要 select 此内联针对大型 table.执行此操作时,您需要避免 PL/pgSQL 的开销。这是一种很棒的语言,我经常使用它,但我会避免将其用于内联 SQL。使用 PL/pgSQL 封装转换逻辑,而不是内联 SQL.
其次,我会将函数设置为 IMMUTABLE,因为您不会在函数中更新数据库,并且给定参数的值总是 returns。更多关于这里:
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 < INTERVAL '00:00:00' THEN + INTERVAL '24:00:00' ELSE 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 中编写了一个 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
我不确定出了什么问题?
现代 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
语句中需要表达式。
Pavel 关于如何修复该函数是 100% 正确的,但基于函数代码并且因为您使用的是 Greenplum,我猜您想要 select 此内联针对大型 table.执行此操作时,您需要避免 PL/pgSQL 的开销。这是一种很棒的语言,我经常使用它,但我会避免将其用于内联 SQL。使用 PL/pgSQL 封装转换逻辑,而不是内联 SQL.
其次,我会将函数设置为 IMMUTABLE,因为您不会在函数中更新数据库,并且给定参数的值总是 returns。更多关于这里: 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 < INTERVAL '00:00:00' THEN + INTERVAL '24:00:00' ELSE 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 功能所需的扫描和内存较少。