7

La mia ultima domanda Passing an array to stored to postgres era un po 'oscura. Ora, per chiarire il mio obiettivo:Unnest multiple array in parallelo

Voglio creare una stored procedure Postgres che accetterà due parametri di input. Uno sarà un elenco di alcuni importi come per esempio (100, 40.5, 76) e l'altro sarà un elenco di alcune fatture ('01-2222-05','01-3333-04','01-4444-08'). Dopo voglio usare questi due elenchi di numeri e personaggi e fare qualcosa con loro. Ad esempio, voglio prendere ogni importo da questa matrice di numeri e assegnarlo alla fattura corrispondente.

Qualcosa di simile in Oracle sarebbe simile a questa:

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

Naturalmente, i due tipi SIMPLEARRAYTYPE e NUMBER_TABLE sono definite in precedenza nel DB.

+0

Qual è chiaro esattamente? Come chiamare * questo tipo di funzioni? È possibile utilizzare i costruttori di array http://www.postgresql.org/docs/current/static/sql-expressions.html#SQL-SYNTAX-ARRAY-CONSTRUCTORS o, è possibile scrivere la loro rappresentazione di input in stringa (quindi utilizzare la fusione facoltativamente http://www.postgresql.org/docs/current/static/arrays.html#ARRAYS-IO – pozs

+0

Non so come creare stored proc con questi tipi di parametri di input. – Maki

+2

Questo è anche trattato nella tua domanda precedente (es. Http://stackoverflow.com/questions/27708234/pl-pgsql-control-structures-for-lists-arrays) - puoi usare lo standard compatibile ' ARRAY', o la sintassi' [] 'specifica di PostgreSQL. http://www.postgresql.org/docs/current/static/arrays.html#ARRAYS-DECLARATION – pozs

risposta

10

potrete amore questa nuova funzione di Postgres 9.4:

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

unnest() con la capacità tanto attesa (almeno per me) di innestare più array in parallelo in modo pulito. The manual:

espandere più array (possibilmente di tipi diversi) in un set di righe. Questo è consentito solo nella clausola FROM;

È un'implementazione speciale del nuovo ROWS FROM feature.

La funzione può ora essere solo:

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;

chiamata:

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

Naturalmente, la forma semplice può essere sostituito con SQL pianura (nessuna funzione aggiuntiva):

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

Nelle versioni precedenti (Postgres 9.3-), è possibile utilizzare il meno elegante e meno sicura forma:

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; 

Avvertimenti della vecchia forma abbreviata: oltre ad essere totalmente non-standard di aver set-ritorno funzione nella lista SELECT e anche unnest in parallelo, invece di formare un prodotto cartesiano, ciò fallirebbe (e si configurerebbe come un prodotto cartesiano) per gli array con un numero di elementi disuguale. Dettagli in queste risposte correlati:

Questo comportamento è stato infine sterilizzata con Postgres . Molteplici funzioni di set-return nell'elenco SELECT producono righe in "lock-step" ora. Vedere:

2

Gli array vengono dichiarati aggiungendo [] al tipo di dati di base. Li dichiara come parametro allo stesso modo in cui si dichiara parametri regolari:

La seguente funzione accetta un array di interi e e array di stringhe e tornerà un testo fittizio:

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

demo SQLFiddle: http://sqlfiddle.com/#!15/fdb8d/1

+0

Ho ricevuto un errore quando ho provato questa chiamata. – Maki

+0

Scusa, mio ​​errore, va bene. Posso usare FOREACH su un array di testo? – Maki

+0

Posso usare FOREACH su array di testo in Postgres? – Maki