0
CREATE OR REPLACE FUNCTION fnMyFunction(recipients recipient[]) ...

    FOREACH v_recipient IN ARRAY recipients
       LOOP
          v_total := v_total + v_recipient.amount;
          INSERT INTO tmp_recipients(id, amount)
          VALUES(v_recipient.id, v_recipient.amount::numeric(10,2));
    END LOOP;

...

これは開発環境ではうまく機能しますが、リリース環境が 8.4 であり、FOREACH コンストラクトをサポートしていないようです。完全なリファクタリングを回避するために、配列パラメーター セットを使用し、同様の方法で配列の値を使用して、ループの代替実装に誰かが光を当ててくれることを期待していました。

私が受け取っているエラーメッセージは次のとおりです。

エラー: "FOREACH" SQL 状態またはその付近での構文エラー: 42601 コンテキスト: 行 ## 付近の PL/PgSQL 関数 "fnMyFunction" の SQL ステートメント

データベース環境は共有ホスト上にあるため、プラットフォームをアップグレードするオプションはありません。
postgres 9.1 と 8.4 にタグを付けました。関数は 9.x では正常に動作しますが、8.4 では失敗するためです。

4

2 に答える 2

2

使用しunnestます。8.4だったと思います。テストされていませんが、正しいと思います:

FOR v_recipient IN SELECT vr FROM unnest(recipients) x(vr)
LOOP
....
END LOOP;

それができない場合はarray_length、配列へのインデックス付けを使用してループオーバーする必要があります。

于 2012-10-02T04:46:54.793 に答える
1

このようにINSERT、一度に 1 つずつ実行します。リレーショナル データベースでは、セット ベースの操作は通常、一度に 1 つずつレコードを反復処理するよりもはるかに高速です。

これはよりシンプルで高速で、PostgreSQL 8.4 以降で動作するはずです。

INSERT INTO tmp_recipients(id, amount)
SELECT (r.col).*
FROM   (SELECT unnest(recipients) AS col) r

これは、配列の複合基本型が (この(id, amount)順序で) で構成され、型をamountに強制できることを前提としていnumeric(10,2)ます。それ以外の場合、または念のため、より明確にします。

INSERT INTO tmp_recipients(id, amount)
SELECT (r.col).id, (r.col).amount::numeric(10,2)
FROM   (SELECT unnest(recipients) AS col) r

括弧(r.col)はオプションではありません。複合型の構文を明確にするために必要です。

于 2012-10-21T23:23:24.810 に答える