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 功能所需的扫描和内存较少。