【问题标题】:Unnest multiple arrays in parallel并行取消嵌套多个数组
【发布时间】:2015-03-06 08:44:05
【问题描述】:

我的最后一个问题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);

当然,SIMPLEARRAYTYPENUMBER_TABLE 这两种类型在前面的 DB 中已经定义好了。

【问题讨论】:

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


【解决方案1】:

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

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

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

【讨论】:

  • 对不起,我的错,没关系。你可以在文本数组上使用 FOREACH 吗?
  • 我可以在 Postgres 中对文本数组使用 FOREACH 吗?
  • @Maki:如果一切都失败了,请阅读手册:postgresql.org/docs/current/static/…
【解决方案2】:

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

<b>unnest(anyarray, anyarray [, ...])</b>

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

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

【讨论】:

  • 文档中关于“rows from”语法的文档有点混乱,没有示例。仅供参考,select * from rows from(unnest('{1,2,3}'::integer[]), unnest('{4,5,6}'::integer[]), unnest('{7,8}'::integer[])) u(a, b, c); 将演示基本用法——“rows from”构造返回一个可在 from 子句中使用的表。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-08-16
  • 1970-01-01
  • 2022-01-10
  • 1970-01-01
  • 1970-01-01
  • 2021-12-05
相关资源
最近更新 更多