¿Cómo agregar una clave primaria de incremento automático a una tabla existente, en PostgreSQL?

Respuestas:

355

( Actualizado - Gracias a las personas que comentaron )

Versiones modernas de PostgreSQL

Supongamos que tiene una tabla llamada test1, a la que desea agregar una idcolumna de clave primaria (sustituto) de incremento automático . El siguiente comando debería ser suficiente en versiones recientes de PostgreSQL:

   ALTER TABLE test1 ADD COLUMN id SERIAL PRIMARY KEY;

Versiones anteriores de PostgreSQL

En las versiones anteriores de PostgreSQL (anteriores a 8.x?) Tenía que hacer todo el trabajo sucio. La siguiente secuencia de comandos debería hacer el truco:

  ALTER TABLE test1 ADD COLUMN id INTEGER;
  CREATE SEQUENCE test_id_seq OWNED BY test1.id;
  ALTER TABLE test ALTER COLUMN id SET DEFAULT nextval('test_id_seq');
  UPDATE test1 SET id = nextval('test_id_seq');

Nuevamente, en versiones recientes de Postgres esto es más o menos equivalente al comando anterior.

leonbloy
fuente
3
Estoy usando ORACLE, por lo que compartirlo podría ser útil para los chicos de ORACLE En ORACLE: ALTER TABLE TEST1 AGREGAR NÚMERO DE ID; ACTUALIZAR TEST1 SET ID = TEST1_SEQ.NEXTVAL; ALTER TABLE TEST1 AGREGAR CLAVE PRIMARIA (ID); crear una secuencia TEST1_SEQ antes de ejecutar la instrucción UPDATE
msbyuva
Tenga en cuenta que ADD PRIMARY KEYtambién crea una NOT NULLrestricción (probada en postgres 9.3) como se esperaba y quería.
Jared Beck
19
En Postgres puedes usar un solo comandoALTER TABLE test1 ADD COLUMN id SERIAL PRIMARY KEY;
resnyanskiy
1
Además del comentario de @ resnyanskiy, esto funcionará incluso cuando haya datos en la tabla. Los ID se rellenan y no se establece una restricción nula. La respuesta completa puede ser reemplazada por la línea en ese comentario.
Synesso
1
@EricWang Gracias, Eric, tienes razón: creo que esto no funcionó hace algunas versiones (años), pero no estoy seguro. Convirtió la respuesta en community-wiki.
leonbloy
57
ALTER TABLE test1 ADD COLUMN id SERIAL PRIMARY KEY;

Esto es todo lo que necesitas para:

  1. Agrega la idcolumna
  2. Rellene con una secuencia del 1 al recuento (*).
  3. Establecerlo como clave principal / no nulo.

Se le da crédito a @resnyanskiy que dio esta respuesta en un comentario.

Synesso
fuente
2
Esto debe marcarse como respuesta, y la respuesta debe pertenecer a @resnyanskiy
Eric Wang
Primero tuve que soltar el pkey y luego ejecutar esto. ALTER TABLE <table> DROP CONSTRAINT <pkey_name>;
Josh Robertson
10

Para usar una columna de identidad en v10,

ALTER TABLE test 
ADD COLUMN id { int | bigint | smallint}
GENERATED { BY DEFAULT | ALWAYS } AS IDENTITY PRIMARY KEY;

Para obtener una explicación de las columnas de identidad, consulte https://blog.2ndquadrant.com/postgresql-10-identity-columns/ .

Para conocer la diferencia entre GENERADO POR DEFECTO y SIEMPRE GENERADO, consulte https://www.cybertec-postgresql.com/en/sequences-gains-and-pitfalls/ .

Para alterar la secuencia, consulte https://popsql.io/learn-sql/postgresql/how-to-alter-sequence-in-postgresql/ .

jhoanna
fuente
El problema con esta solución es que si la tabla ya contiene filas, aparece un error:SQL Error [23502]: ERROR: column "id" contains null values
isapir
3
@isapir: Hubo un error en las primeras versiones (pág. 10 y 10.1) que produjo este error. Se solucionó con la página 10.2. Detalles aquí: dba.stackexchange.com/q/200143/3684
Erwin Brandstetter
Gracias @ erwin-brandstetter
isapir
Un año después encontré esta respuesta nuevamente, error aparentemente corregido, votado;)
isapir
2

Aterricé aquí porque también estaba buscando algo así. En mi caso, estaba copiando los datos de un conjunto de tablas de preparación con muchas columnas en una tabla mientras asignaba identificadores de fila a la tabla de destino. Aquí hay una variante de los enfoques anteriores que utilicé. Agregué la columna de serie al final de mi tabla de destino. De esa manera, no tengo que tener un marcador de posición en la instrucción Insert. Luego, una simple selección * en la tabla de destino rellenó automáticamente esta columna. Aquí están las dos declaraciones SQL que utilicé en PostgreSQL 9.6.4.

ALTER TABLE target ADD COLUMN some_column SERIAL;
INSERT INTO target SELECT * from source;
Dean Sha
fuente