2012-02-01 12 views
10

Sto inserendo record di massa utilizzando la dichiarazione COPY in PostgreSQL. Quello che realizzo è che gli ID di sequenza non vengono aggiornati e quando provo a inserire un record in un secondo momento, genera un ID di sequenza duplicato. Devo aggiornare manualmente il numero di sequenza per ottenere il numero di record dopo aver eseguito COPY? Non c'è una soluzione durante l'esecuzione di COPY, basta incrementare la variabile di sequenza, cioè il campo chiave primaria della tabella? Per favore, chiariscimi su questo. Grazie in anticipo!Perché le sequenze non vengono aggiornate quando COPY viene eseguito in PostgreSQL?

Ad esempio, se inserisco 200 record, COPY funziona correttamente e la mia tabella mostra tutti i record. Quando inserisco manualmente un record in un secondo momento, si dice duplicate sequence ID error. Molto bene implica che non ha incrementato gli ID di sequenza durante la COPIA come funziona bene durante la normale INSERT. Invece di istruire l'ID della sequenza per impostare il numero massimo di record, non ci sarà alcun meccanismo per educare il comando COPY per incrementare gli ID di sequenza durante la sua opzione di COPYing in blocco?

risposta

3

È possibile copiare su una tabella sorella, quindi insert into mytable select * from sister - che incrementerebbe la sequenza.

Se i dati caricati ha il campo id, non selezionare l'opzione per l'inserimento: insert into mytable (col1, col2, col3) select col1, col2, col3 from sister

+0

grazie per il vostro pensiero qui! – siva

+0

+1 che funzionerà – pilcrow

20

Tu chiedi:

Devo aggiornare manualmente il numero di sequenza per ottenere il numero di record dopo aver eseguito la copia?

Sì, si dovrebbe, come documented here:

Aggiornare il valore della sequenza dopo una copia da:

| BEGIN; 
| COPY distributors FROM 'input_file'; 
| SELECT setval('serial', max(id)) FROM distributors; 
| END; 

Scrive:

esso non ha incrementato gli ID di sequenza durante la COPIA come funzionano bene durante la normale INSERISIONE

Ma non è così! :) Quando si esegue un INSERT normale, in genere non si specifica un valore esplicito per la chiave primaria supportata da SEQUENCE. Se così fosse, si potrebbe correre per gli stessi problemi si stanno avendo ora:

postgres=> create table uh_oh (id serial not null primary key, data char(1)); 
NOTICE: CREATE TABLE will create implicit sequence "uh_oh_id_seq" for serial column "uh_oh.id" 
NOTICE: CREATE TABLE/PRIMARY KEY will create implicit index "uh_oh_pkey" for table "uh_oh" 
CREATE TABLE 
postgres=> insert into uh_oh (id, data) values (1, 'x'); 
INSERT 0 1 
postgres=> insert into uh_oh (data) values ('a'); 
ERROR: duplicate key value violates unique constraint "uh_oh_pkey" 
DETAIL: Key (id)=(1) already exists. 

vostro comando COPY, naturalmente, è la fornitura di un valore esplicito id, proprio come l'esempio INSERT sopra.

+0

La sequenza si incrementa solo quando un valore viene "consumato" da esso per riempire il valore predefinito durante un INSERIMENTO (internamente utilizza la funzione nextval). Se fornisci valori per il tuo ID, la sequenza non viene utilizzata, quindi non si sposta. – peufeu

+0

@peufeu, sì, giusto – pilcrow

5

Mi rendo conto che questo è un po 'vecchio ma forse qualcuno potrebbe ancora cercare la risposta.

Come altri COPY detto funziona in modo simile a INSERT, quindi per l'inserimento in una tabella che ha una sequenza, semplicemente non si menziona il campo della sequenza e si è preso cura di te. Per COPY funziona nello stesso modo. Ma non COPY richiede che tutti i campi nella tabella siano presenti nel file di testo? La risposta corretta è NO, non lo è, ma è il comportamento predefinito.

Per copiare e lasciare la sequenza fuori effettuare le seguenti operazioni:

COPY $YOURSCHEMA.$YOURTABLE(col1,col2,col3,col4) FROM '$your_input_file' DELIMITER ',' CSV HEADER; 

Non c'è bisogno di aggiornare manualmente lo schema seguito, funziona come previsto e nel mio test è solo più veloce.

+1

Giusto per aggiungere a questo, il file sorgente (input) deve avere solo le colonne che stai copiando in esso. Postgres non è "intelligente" - non guarda le intestazioni delle colonne per abbinare le colonne che hai nominato nel comando copia. Quindi, nell'esempio di @Phobos sopra, il file di input deve avere solo 4 colonne. Spero solo di salvare qualcuno senza problemi - questa risposta mi ha aiutato. –

Problemi correlati