最平行的多个数组
我的最后一个问题传递一个数组存储到postgres是有点不清楚。 现在,澄清我的目标:
我想创build一个Postgres存储过程,它将接受两个input参数。 其中一个是一些金额的列表,例如(100, 40.5, 76)
('01-2222-05','01-3333-04','01-4444-08')
(100, 40.5, 76)
,另一个是一些发票清单 ('01-2222-05','01-3333-04','01-4444-08')
。 之后,我想使用这两个数字和字符列表,并与他们做一些事情。 例如,我想从这个数组中获取每个金额,并将其分配给相应的发票。
在Oracle中类似这样的东西:
SOME_PACKAGE.SOME_PROCEDURE ( 789, SYSDATE, SIMPLEARRAYTYPE ('01-2222-05','01-3333-04','01-4444-08'), NUMBER_TABLE (100,40.5,76), 'EUR', 1, P_CODE, P_MESSAGE);
当然,这两种typesSIMPLEARRAYTYPE
和NUMBER_TABLE
是在DB中定义的。
你会喜欢 Postgres 9.4的这个新function:
unnest(anyarray, anyarray [, ...])
unnest()
与备受期待的(至less是我)能够并行干净的并行多个数组。 手册:
将多个数组(可能是不同types)展开为一组行。 这只在FROM子句中是允许的。
这是新的ROWS FROM
特性的特殊实现。
你的function现在可以是:
CREATE OR REPLACE FUNCTION multi_unnest(_some_id int , _amounts numeric[] , _invoices text[]) RETURNS TABLE (some_id int, amount numeric, invoice text) AS $func$ SELECT _some_id, u.* FROM unnest(_amounts, _invoices) u; $func$ LANGUAGE sql;
呼叫:
SELECT * FROM multi_unnest(123, '{100, 40.5, 76}'::numeric[] , '{01-2222-05,01-3333-04,01-4444-08}'::text[]);
当然,简单的forms可以用普通的SQL (没有附加的function)replace:
SELECT 123 AS some_id, * FROM unnest('{100, 40.5, 76}'::numeric[] , '{01-2222-05,01-3333-04,01-4444-08}'::text[]) AS u(amount, invoice);
在早期版本(Postgres 9.3- )中,可以使用不太优雅和不太安全的forms:
SELECT 123 AS some_id , unnest('{100, 40.5, 76}'::numeric[]) AS amount , unnest('{01-2222-05,01-3333-04,01-4444-08}'::text[]) AS invoice;
旧的速记forms的注意事项:除了完全不规范的在SELECT
列表中设置返回函数,甚至是并行而不是形成笛卡儿积,这将失败(并默认为笛卡尔积)元素数量不等。 这些相关答案的细节:
- 在PostgreSQL中并行unnest()和sorting顺序
- PostgreSQL中是否有类似zip()函数的组合两个数组?
这个行为终于被Postgres 10消毒了。 SELECT
列表中的多个设置返回函数现在会在“locking步骤”中生成行。 看到:
- select子句中多个设置返回函数的期望行为是什么?
通过将[]
添加到基本数据types来声明数组。 你声明他们作为一个参数,就像你声明常规参数一样:
下面的函数接受一个整数和string数组,并返回一些哑元文本:
create function array_demo(p_data integer[], p_invoices text[]) returns text as $$ select p_data[1] || ' => ' || p_invoices[1]; $$ language sql; select array_demo(array[1,2,3], array['one', 'two', 'three']);
SQLFiddle演示: http ://sqlfiddle.com/#!15/fdb8d/1