2016-05-20 17 views
1

私はGreenplumにPL/pgSQL関数を作成していましたが、関数はinterval< interval '00:00:00'を正の値に変換する必要があります。Greenplum plpgsql関数は入力の最後に構文エラーを返します

たとえば、間隔値-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 

私が間違って何が起こっているのかわかりませんか?

+1

私は、関数の呼び出し後にエラーが発生したと思います。その呼び出しを私たちに示してください。 – Darek

+1

あなたは何個の 'abstime'関数を持っていますか?.. –

+0

実際には私はこの関数を全く呼び出さなかったので、' enter'を押した後にこのエラーが表示されるので、私の '\ df' – cinqS

答えて

2

Pavelは関数の修正方法を100%正確にしていますが、機能コードに基づいており、Greenplumを使用しているため、大きな表に対してこのインラインを選択したいと思っています。これを行うとき、PL/pgSQLのオーバーヘッドを避けたいでしょう。それは素晴らしい言語であり、頻繁に使用しますが、インラインSQLの場合は避けています。インラインSQLではなく、変換ロジックをカプセル化するためにPL/pgSQLを使用してください。

第2に、関数内でデータベースを更新していないため、同じ値が常に指定されたパラメータに対して返されるため、関数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機能に必要なスキャンとメモリが少なくなりました。

+0

ああ、これは本当に役に立ち、はい、私はGreenplumを使用しているので、私はリソースのコストを考慮する必要があります。 – cinqS

3

現代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文で必要です。

+0

はい、ありがとうございます。私は 'postgresql v8.2'に基づいて' greenplum'を使っています。 – cinqS

関連する問題