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 语句靠近行 ##

db 环境位于共享主机上,因此我没有平台升级选项。
我标记了 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。对于关系数据库,基于集合的操作通常比一次遍历一个记录要快得多

这应该更简单、更快,并且适用于 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 回答