并联多个阵列

时间:2015-01-08 09:22:59

标签: arrays postgresql arraylist plpgsql set-returning-functions

我的上一个问题Passing an array to stored to postgres有点不清楚。现在,澄清我的目标:

我想创建一个Postgres存储过程,它将接受两个输入参数。一个是金额的列表,例如(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);

当然,早期在DB中定义了SIMPLEARRAYTYPENUMBER_TABLE这两种类型。

2 个答案:

答案 0 :(得分:17)

你将 Postgres的这一新功能 9.4

    unnest(anyarray, anyarray [, ...])

unnest()非常期待(至少是我)能够并行排除多个阵列干净地The manual:

  

将多个数组(可能是不同类型)扩展为一组行。这只能在FROM子句中使用;

这是新ROWS FROM feature的特殊实现。

您的功能现在可以是:

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[]);

当然,简单表单可以替换为普通SQL (无附加功能):

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 - )中,您可以使用不那么优雅且不太安全的形式:

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;

旧速记形式的注意事项:除了在SELECT列表中具有设置返回功能的非标准之外,返回的行数将是每个数组元素数量的最低公倍数(令人惊讶的是不等数的结果)。这些相关答案的详细信息:

此行为最终已使用 Postgres 10 进行了清理。 SELECT列表中的多个集合返回函数会在"锁定步骤"中生成行。现在。参见:

答案 1 :(得分:3)

通过将[]添加到基本数据类型来声明数组。您将它们声明为参数,与声明常规参数的方式相同:

以下函数接受一个整数数组和字符串数组,并返回一些虚拟文本:

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