最平行的多个数组

我的最后一个问题传递一个数组存储到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); 

当然,这两种typesSIMPLEARRAYTYPENUMBER_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