2012-02-01 45 views
10

estoy insertar registros a granel usando COPY comunicado en PostgreSQL. Lo que me doy cuenta es que los identificadores de secuencia no se actualizan y cuando intento insertar un registro más tarde, arroja una identificación de secuencia duplicada. ¿Debo actualizar manualmente el número de secuencia para obtener el número de registros después de realizar COPY? ¿No hay una solución al realizar COPY, simplemente incremente la variable de secuencia, es decir, el campo de clave principal de la tabla? Por favor, aclarame sobre esto. ¡Gracias por adelantado!¿Por qué las secuencias no se actualizan cuando se realiza COPY en PostgreSQL?

Por ejemplo, si inserto 200 registros, COPY hace el bien y mi tabla muestra todos los registros. Cuando inserto manualmente un registro más tarde, dice duplicate sequence ID error. Esto implica muy bien que no incrementó los ID de secuencia durante la COPIA, ya que funcionan bien durante la INSERCIÓN normal. En lugar de instruir a la secuencia ID para establecer el número máximo de registros, no va a haber ningún mecanismo para educar el comando COPY para incrementar los identificadores de secuencia durante su opción de copia masiva?

Respuesta

3

Se puede copiar en una mesa hermana, a continuación, insert into mytable select * from sister - que incrementará la secuencia.

Si los datos cargado tiene el campo id, no lo seleccione para la inserción: insert into mytable (col1, col2, col3) select col1, col2, col3 from sister

+0

gracias por su pensamiento aquí! – siva

+0

+1 que funcionará – pilcrow

20

Usted pregunta:

¿Debo actualizar manualmente el número de secuencia para obtener el número de registros después de realizar COPIA?

sí, usted debe, como documented here:

actualización del valor de secuencia después de una copia de:

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

escribe:

se no incrementó los identificadores de secuencia durante la copia tan bien durante el trabajo normal de la inserción de

Pero eso no es así! :) Cuando realiza un INSERT normal, generalmente no especifica un valor explícito para la clave primaria respaldada por SEQUENCE. Si lo hiciera, tendría que ejecutar a los mismos problemas que usted está teniendo ahora:

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. 

Su comando COPY, por supuesto, está suministrando un valor explícito id, al igual que el ejemplo anterior debe insertarse.

+0

La secuencia solo aumenta cuando se "consume" un valor de ella para completar el valor predeterminado durante un INSERT (internamente usa la función nextval). Si proporciona valores para su ID, la secuencia no se usa, por lo tanto, no se mueve. – peufeu

+0

@peufeu, sí, es correcto – pilcrow

5

que se dan cuenta de que esto es un poco viejo, pero tal vez alguien todavía podría estar buscando la respuesta.

Como otros dicen COPY funciona de forma similar a INSERT, por lo que para insertar en una tabla que tiene una secuencia, simplemente no menciona el campo de secuencia y se ocupa de usted. Para COPY, funciona de la misma manera. Pero, ¿COPY no requiere que TODOS los campos de la tabla estén presentes en el archivo de texto? La respuesta correcta es NO, no, pero es el comportamiento predeterminado.

para copiar y dejar la secuencia fuera haga lo siguiente:

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

No hay necesidad de actualizar manualmente el esquema después, funciona según lo previsto y en mis pruebas es casi tan rápido.

+1

Solo para agregar a esto, el archivo de origen (entrada) necesita tener solo las columnas que está copiando en él. Postgres no es "inteligente": no mira los encabezados de columna para hacer coincidir las columnas que ha nombrado en el comando de copia. Entonces, en el ejemplo anterior de @Phobos, el archivo de entrada solo debe tener 4 columnas. Solo con la esperanza de salvar a alguien con algunas molestias, esta respuesta me ayudó. –

Cuestiones relacionadas