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上下文:SQL PL / PgSQL函数中的语句“fnMyFunction”在##
附近
db环境位于共享主机上,因此我没有平台升级选项 我标记了postgres 9.1和8.4,因为该函数在9.x中正常工作但在8.4上失败。
答案 0 :(得分:2)
使用unnest
;我认为这是在8.4。未经测试但我认为是对的:
FOR v_recipient IN SELECT vr FROM unnest(recipients) x(vr)
LOOP
....
END LOOP;
如果你不能这样做,你将不得不使用索引到数组中循环array_length
。
答案 1 :(得分: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)
周围的括号不是可选的。他们需要消除复合类型的语法歧义。