为了论证,我有一个简单的表格。我有一个选择 id 并循环遍历它们的函数,称为loop_test
. 我可以选择一组 id 并循环遍历它们,从而导致我在事务中发生更改。
CREATE OR REPLACE FUNCTION loop_test() RETURNS void AS $$
DECLARE
_ids_array INTEGER[];
_id INTEGER;
BEGIN
SELECT ARRAY(SELECT id FROM loop_test) INTO _ids_array;
FOREACH _id IN ARRAY _ids_array
LOOP
UPDATE loop_test SET looped = TRUE WHERE id = _id;
END LOOP;
END;
$$ LANGUAGE plpgsql;
桌子:
db=# \d loop_test;
Table "public.loop_test"
Column | Type | Modifiers
---------------+---------+-----------
id | integer |
other_id | integer |
id_copy | integer |
other_id_copy | integer |
looped | boolean |
db=# select * from loop_test;
id | other_id | id_copy | other_id_copy | looped
----+----------+---------+---------------+--------
1 | 10 | | |
6 | 15 | | |
2 | 11 | | |
7 | 16 | | |
3 | 12 | | |
4 | 13 | | |
5 | 14 | | |
(7 rows)
当我打电话时select loop_test()
,我得到以下结果:
db=# select * from loop_test;
id | other_id | id_copy | other_id_copy | looped
----+----------+---------+---------------+--------
1 | 10 | | | t
6 | 15 | | | t
2 | 11 | | | t
7 | 16 | | | t
3 | 12 | | | t
4 | 13 | | | t
5 | 14 | | | t
(7 rows)
但是,我想创建一个函数来选择 theid
和 theother_id
到一个数组中。有人告诉我使用类似的东西agg_array
,但我不完全理解它是如何工作的。
我在想像下面这样的事情?
CREATE OR REPLACE FUNCTION agg_loop_test() RETURNS void AS $$
DECLARE
_ids_array INTEGER[][];
_id INTEGER;
BEGIN
SELECT AGG_ARRAY(SELECT id, other_id FROM loop_test) INTO _ids_array;
FOREACH _id IN ARRAY _ids_array
LOOP
UPDATE loop_test SET id_copy = _id[0], other_id_copy = _id[1] WHERE id = _id[0];
END LOOP;
END;
$$ LANGUAGE plpgsql;
一个更好的方法,但是:只需更新。不需要循环。
该
WHERE
条件仅在id
可以为 null 并且您想要与您所拥有的完全等价的情况下才有用。环形
如果您只是在探索循环 - 您可以分配多个变量:
虽然您只需要已知类型的两列,但这可能比获取整个(可能很大)行便宜一些。
我不了解多维数组,但我找到了一种更好的方法来做我想做的事情:
@Erwin 的回复是绝对正确的。将数组用于描述的示例是性能错误(不幸的是,很常见)。有时它可能是必要的——因为您需要将一些值作为函数参数传递。
有两种技术 - 1. 传递复合值数组,2. 传递多维数组。对我来说,性能应该是 +/- 相同的 - 在某些情况下,使用复合数组可能更具可读性。不确定,是否可以从 9.3 的查询结果创建多维数组。
可能仍然只能使用一个
UPDATE
没有循环的语句 with functionunnest
:性能影响取决于数组的大小——对于小数组来说,它是最小的——但仍然可能存在更深的循环嵌套,并且可能存在性能问题。
对于多维数组PLpgSQL
FOREACH
语句有SLICE
子句: