并行解除多个数组的嵌套

问题描述 投票:0回答:2

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

当然,

SIMPLEARRAYTYPE
NUMBER_TABLE
这两种类型是之前在DB中定义的。

arrays postgresql arraylist plpgsql set-returning-functions
2个回答
49
投票

您会喜欢Postgres 9.4的这个新功能:

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

unnest()
具有备受期待(至少对我来说)的能力,可以干净地并行解除多个数组的嵌套。 说明书:

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

这是新的

ROWS FROM
功能的特殊实现。

您的功能现在可以是:

CREATE OR REPLACE FUNCTION multi_unnest(_some_id int
                                      , _amounts numeric[]
                                      , _invoices text[])
  RETURNS TABLE (some_id int, amount numeric, invoice text)
  LANGUAGE sql AS
$func$
SELECT _some_id, u.* FROM unnest(_amounts, _invoices) u;
$func$;

致电:

SELECT * FROM multi_unnest(123, '{100, 40.5, 76}'::numeric[] 
                        , '{01-2222-05,01-3333-04,01-4444-08}'::text[]);

当然,简单的形式可以替换为plain 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
列表中的多个返回集合的函数现在以“锁步”方式生成行。参见:


5
投票

数组是通过将

[]
添加到基本数据类型来声明的。您可以像声明常规参数一样将它们声明为参数:

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

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

© www.soinside.com 2019 - 2024. All rights reserved.