2009-05-22 8 views
16

Esiste un modo conciso per selezionare il valore successivo per una sequenza PostgreSQL più volte in 1 query? Questo sarebbe l'unico valore restituito.Seleziona più ID da una sequenza PostgreSQL

Per esempio, mi piacerebbe fare qualcosa di veramente breve e dolce come:

SELECT NEXTVAL('mytable_seq', 3) AS id; 

E ottenere:

id 
----- 
118 
119 
120 
(3 rows) 

risposta

38
select nextval('mytable_seq') from generate_series(1,3); 

generate_series è una funzione che restituisce il numero di righe con numeri sequenziali, configurati da esso è argomenti.

Nell'esempio precedente, non ci interessa il valore in ogni riga, usiamo generate_series come generatore di righe. E per ogni riga possiamo chiamare nextval. In questo caso restituisce 3 numeri (nextvals).

È possibile eseguire il wrapping di questa funzione, ma non sono sicuro che sia davvero sensato, data la brevità della query.

+0

ESATTAMENTE quello che stavo cercando, grazie! –

+3

Si noti che i 3 numeri (nextvals) non sono garantiti per essere sequenziali. – cquezel

0

Il mio migliore soluzione attuale è:

SELECT NEXTVAL('mytable_seq') AS id 
UNION ALL 
SELECT NEXTVAL('mytable_seq') AS id 
UNION ALL 
SELECT NEXTVAL('mytable_seq') AS id; 

Quale restituirà correttamente 3 righe ... ma mi piacerebbe qualcosa che sia SQL minimale per almeno 100 o più invoice NEXTVAL cationi.

1

CREATE OR REPLACE FUNCTION foo() RETURNS SETOF INT AS $$ 
DECLARE 
    seqval int; x int; 
BEGIN 
x := 0; 

WHILE x < 100 LOOP 
    SELECT into seqval nextval('f_id_seq'); 
    RETURN NEXT seqval; 
    x := x+1; 
END LOOP; 
RETURN; 
END; 
$$ LANGUAGE plpgsql STRICT; 

Naturalmente, se tutto quello che sta cercando di fare è avanzare la sequenza, c'è setval().

Si potrebbe anche avere la funzione di prendere un parametro per quante volte per ciclo:

CREATE OR REPLACE FUNCTION foo(loopcnt int) RETURNS SETOF INT AS $$ 
DECLARE 
    seqval int;  
    x int; 
BEGIN 
x := 0; 
WHILE x < loopcnt LOOP 
    SELECT into seqval nextval('f_id_seq'); 
    RETURN NEXT seqval;x := x+1; 
END LOOP; 
RETURN; 
END; 
$$ LANGUAGE plpgsql STRICT; 
+0

Si noti che a causa dell'uso di "setof", si deve chiamare questo come tabella: 'select * from foo (500);' – TML

0

A meno che non si desideri realmente restituire tre righe, impostare la sequenza su "INCREMENTO DI 3" per ciascuna selezione. Quindi è possibile aggiungere semplici 1 e 2 al risultato che hanno i tre numeri di sequenza.

Ho tentato di aggiungere un collegamento ai documenti postgresql, ma apparentemente non sono autorizzato a postare collegamenti.

+0

Apprezzato, ma le svalutazioni evidenziate nel collegamento da Ants Aasma sono troppo ripide per me per modificare l'incremento ... e il numero di id di cui ho bisogno varia, quindi preferisco ottenere tutti gli id ​​individualmente (il che rende il codice che usa gli id ​​più semplici comunque). –

11

C'è un grande articolo su questo problema esatto: "getting multiple values from sequences".

Se le prestazioni non è un problema, per esempio quando si utilizzano i valori della sequenza nani il tempo impiegato per ottenere loro o n è piccolo, poi il SELEZIONA nextval ('ss') FROM generate_series (1, n) l'approccio è il più semplice e il più appropriato.

Tuttavia, quando si preparano i dati per i carichi di massa, l'ultimo approccio dall'articolo di incremento della sequenza da n dall'interno di un blocco è appropriato.

+0

È interessante notare che l'articolo sembra essere stato scritto dalla persona che ha scritto la risposta che ho accettato :-) Indipendentemente da ciò, la serie_di_risposta soddisfa le mie esigenze perché il numero di ID di cui ho bisogno è di circa una dozzina. In un caso molto raro, forse 100 ... quindi le cadute dell'altra soluzione presentate nell'articolo sono troppo ripide per i miei usi. +1 per il bel collegamento però! –