PostgreSQL Autoincrement

Estoy cambiando de MySQL a PostgreSQL y me preguntaba cómo puedo hacer los valores de autoincrement. Vi en los documentos de PostgreSQL un tipo de datos “serial”, pero obtengo errores de syntax al usarlo (en v8.0).

Sí, SERIAL es la función equivalente.

CREATE TABLE foo ( id SERIAL, bar varchar); INSERT INTO foo (bar) values ('blah'); INSERT INTO foo (bar) values ('blah'); SELECT * FROM foo; 1,blah 2,blah 

SERIAL es solo una macro de creación de tiempo de tabla alrededor de las secuencias. No puede alterar SERIAL en una columna existente.

Puede usar cualquier otro tipo de datos enteros , como smallint .

Ejemplo:

 CREATE SEQUENCE user_id_seq; CREATE TABLE user ( user_id smallint NOT NULL DEFAULT nextval('user_id_seq') ); ALTER SEQUENCE user_id_seq OWNED BY user.user_id; 

Es mejor utilizar su propio tipo de datos, en lugar del tipo de datos en serie del usuario.

Si desea agregar una secuencia a la ID en la tabla que ya existe, puede usar:

 CREATE SEQUENCE user_id_seq; ALTER TABLE user ALTER user_id SET DEFAULT NEXTVAL('user_id_seq'); 

Si bien parece que las secuencias son equivalentes a MySQL auto_increment, existen algunas diferencias sutiles pero importantes:

1. Consultas Fallidas Incrementan la Secuencia / Serie

La columna de serie se incrementa en consultas fallidas. Esto lleva a la fragmentación de consultas fallidas, no solo eliminaciones de filas. Por ejemplo, ejecute las siguientes consultas en su base de datos PostgreSQL:

 CREATE TABLE table1 ( uid serial NOT NULL PRIMARY KEY, col_b integer NOT NULL, CHECK (col_b>=0) ); INSERT INTO table1 (col_b) VALUES(1); INSERT INTO table1 (col_b) VALUES(-1); INSERT INTO table1 (col_b) VALUES(2); SELECT * FROM table1; 

Debería obtener el siguiente resultado:

  uid | col_b -----+------- 1 | 1 3 | 2 (2 rows) 

Observe cómo uid va de 1 a 3 en lugar de 1 a 2.

Esto todavía ocurre si creara manualmente su propia secuencia con:

 CREATE SEQUENCE table1_seq; CREATE TABLE table1 ( col_a smallint NOT NULL DEFAULT nextval('table1_seq'), col_b integer NOT NULL, CHECK (col_b>=0) ); ALTER SEQUENCE table1_seq OWNED BY table1.col_a; 

Si desea probar cómo MySQL es diferente, ejecute lo siguiente en una base de datos MySQL:

 CREATE TABLE table1 ( uid int unsigned NOT NULL AUTO_INCREMENT PRIMARY KEY, col_b int unsigned NOT NULL ); INSERT INTO table1 (col_b) VALUES(1); INSERT INTO table1 (col_b) VALUES(-1); INSERT INTO table1 (col_b) VALUES(2); 

Debería obtener lo siguiente sin fragmentación :

 +-----+-------+ | uid | col_b | +-----+-------+ | 1 | 1 | | 2 | 2 | +-----+-------+ 2 rows in set (0.00 sec) 

2. Configurar manualmente el valor de la columna serie puede provocar fallas en futuras consultas.

Esto fue señalado por @trev en una respuesta anterior.

Para simular esto, configure manualmente el uid en 4, que luego “chocará”.

 INSERT INTO table1 (uid, col_b) VALUES(5, 5); 

Datos de tabla:

  uid | col_b -----+------- 1 | 1 3 | 2 5 | 5 (3 rows) 

Ejecute otra inserción:

 INSERT INTO table1 (col_b) VALUES(6); 

Datos de tabla:

  uid | col_b -----+------- 1 | 1 3 | 2 5 | 5 4 | 6 

Ahora si ejecuta otra inserción:

 INSERT INTO table1 (col_b) VALUES(7); 

Fallará con el siguiente mensaje de error:

ERROR: el valor duplicado de la clave viola la restricción única “table1_pkey” DETAIL: Key (uid) = (5) ya existe.

Por el contrario, MySQL manejará esto con gracia como se muestra a continuación:

 INSERT INTO table1 (uid, col_b) VALUES(4, 4); 

Ahora inserte otra fila sin configurar el uid

 INSERT INTO table1 (col_b) VALUES(3); 

La consulta no falla, uid solo salta a 5:

 +-----+-------+ | uid | col_b | +-----+-------+ | 1 | 1 | | 2 | 2 | | 4 | 4 | | 5 | 3 | +-----+-------+ 

Las pruebas se realizaron en MySQL 5.6.33, para Linux (x86_64) y PostgreSQL 9.4.9

A partir de Postgres 10, también se admiten las columnas de identidad definidas por el estándar SQL:

 create table foo ( id integer generated always as identity ); 

crea una columna de identidad que no se puede anular a menos que se solicite explícitamente. La siguiente inserción fallará con una columna definida como generated always :

 insert into foo (id) values (1); 

Sin embargo, esto puede ser invalidado:

 insert into foo (id) overriding system value values (1); 

Cuando se usa la opción generated by default este es esencialmente el mismo comportamiento que la implementación en serial existente:

 create table foo ( id integer generated by default as identity ); 

Cuando se proporciona un valor manualmente, la secuencia subyacente también se debe ajustar manualmente, al igual que con una columna en serial .


Una columna de identidad no es una clave principal por defecto (al igual que una columna en serial ). Si debe ser uno, una restricción de clave primaria debe definirse manualmente.

Debe tener cuidado de no insertar directamente en su SERIE o campo de secuencia; de lo contrario, su escritura fallará cuando la secuencia scope el valor insertado:

 -- Table: "test" -- DROP TABLE test; CREATE TABLE test ( "ID" SERIAL, "Rank" integer NOT NULL, "GermanHeadword" "text" [] NOT NULL, "PartOfSpeech" "text" NOT NULL, "ExampleSentence" "text" NOT NULL, "EnglishGloss" "text"[] NOT NULL, CONSTRAINT "PKey" PRIMARY KEY ("ID", "Rank") ) WITH ( OIDS=FALSE ); -- ALTER TABLE test OWNER TO postgres; INSERT INTO test("Rank", "GermanHeadword", "PartOfSpeech", "ExampleSentence", "EnglishGloss") VALUES (1, '{"der", "die", "das", "den", "dem", "des"}', 'art', 'Der Mann küsst die Frau und das Kind schaut zu', '{"the", "of the" }'); INSERT INTO test("ID", "Rank", "GermanHeadword", "PartOfSpeech", "ExampleSentence", "EnglishGloss") VALUES (2, 1, '{"der", "die", "das"}', 'pron', 'Das ist mein Fahrrad', '{"that", "those"}'); INSERT INTO test("Rank", "GermanHeadword", "PartOfSpeech", "ExampleSentence", "EnglishGloss") VALUES (1, '{"der", "die", "das"}', 'pron', 'Die Frau, die nebenen wohnt, heißt Renate', '{"that", "who"}'); SELECT * from test; 

En el contexto de la pregunta formulada y en respuesta al comentario de @ sereja1c, la creación de SERIAL crea secuencias de forma implícita, por lo que para el ejemplo anterior

 CREATE TABLE foo (id SERIAL,bar varchar); 

CREATE TABLE crearía implícitamente la secuencia foo_id_seq para la columna serial foo.id Por lo tanto, SERIAL [4 Bytes] es bueno para su facilidad de uso a menos que necesite un tipo de datos específico para su id.

Lo siento, para repetir una vieja pregunta, pero esta fue la primera pregunta / respuesta de Stack Overflow que apareció en Google.

Esta publicación (que apareció primero en Google) habla sobre el uso de la syntax más actualizada para PostgreSQL 10: https://blog.2ndquadrant.com/postgresql-10-identity-columns/

que sucede ser:

 CREATE TABLE test_new ( id int GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, ); 

Espero que ayude 🙂

De esta manera funcionará con seguridad, espero que ayude:

 CREATE TABLE fruits( id SERIAL PRIMARY KEY, name VARCHAR NOT NULL ); INSERT INTO fruits(id,name) VALUES(DEFAULT,'apple'); or INSERT INTO fruits VALUES(DEFAULT,'apple'); 

Puede verificar esto en el siguiente enlace: http://www.postgresqltutorial.com/postgresql-serial/