web-dev-qa-db-ja.com

複数のアレイを並列にネスト解除します

私の最後の質問 配列をpostgresに格納するために渡す は少し不明確でした。さて、私の目的を明確にするために:

2つの入力パラメーターを受け入れるPostgresストアドプロシージャを作成したいと思います。 1つは、たとえば(100, 40.5, 76)のようないくつかののリストになり、もう1つはいくつかの請求書('01-2222-05','01-3333-04','01-4444-08')。その後、これら2つの数字と文字のリストを使用して、何かを実行したいと思います。たとえば、この数字の配列から各金額を取得して、対応する請求書に割り当てたいと思います。

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

もちろん、2つのタイプSIMPLEARRAYTYPENUMBER_TABLEはDBで以前に定義されています。

14
Maki

あなたは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) 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);

以前のバージョン(Postgres9.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リストにset-returning関数があることは非標準であることに加えて、返される行数は、各配列の要素数の最小公倍数になります(等しくない数)。これらの関連する回答の詳細:

この動作は最終的にPostgres 10でサニタイズされました。 SELECTリスト内の複数のセットを返す関数は、「ロックステップ」で行を生成するようになりました。見る:

20

配列は、基本データ型に[]を追加することによって宣言されます。通常のパラメーターを宣言するのと同じ方法で、それらをパラメーターとして宣言します。

次の関数は、整数の配列と文字列の配列を受け入れ、ダミーテキストを返します。

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