with setval secuencia reiniciar postgres postgresql primary-key database-sequence

postgresql - setval - ¿Cómo restablecer la secuencia de clave principal de Postgres cuando no está sincronizada?



set sequence id postgres (25)

Algunas respuestas realmente graves aquí, supongo que solían ser muy malas en el momento en que se ha pedido esto, ya que muchas respuestas de aquí no funcionan para la versión 9.3. La documentation desde la versión 8.0 proporciona una respuesta a esta pregunta:

SELECT setval(''serial'', max(id)) FROM distributors;

Además, si necesita ocuparse de los nombres de secuencia que distinguen entre mayúsculas y minúsculas, así es como lo hace:

SELECT setval(''"Serial"'', max(id)) FROM distributors;

Me encontré con el problema de que mi secuencia de clave principal no está sincronizada con las filas de la tabla.

Es decir, cuando inserto una nueva fila, aparece un error de clave duplicada porque la secuencia implícita en el tipo de datos en serie devuelve un número que ya existe.

Parece ser causado por la importación / restauración que no mantiene la secuencia correctamente.


El camino más corto y rápido :

SELECT setval(''tbl_tbl_id_seq'', max(tbl_id)) FROM tbl;

tbl_id es la columna en serial de la tabla tbl , que se extrae de la secuencia tbl_tbl_id_seq (que es el nombre automático predeterminado).

Si no conoce el nombre de la secuencia adjunta (que no tiene que estar en forma predeterminada), use pg_get_serial_sequence() :

SELECT setval(pg_get_serial_sequence(''tbl'', ''tbl_id''), max(tbl_id)) FROM tbl;

No hay error off-by-one aquí. Por documentación:

La forma de dos parámetros establece el último campo de valor de la secuencia en el valor especificado y establece su campo is_called en verdadero, lo que significa que el siguiente próximo nextval avanzará la secuencia antes de devolver un valor.

Énfasis en negrita el mio

Concurrencia

No hay defensa contra la actividad de secuencia concurrente o las escrituras en la tabla en las consultas anteriores, todavía. Si eso es relevante, puede bloquear la tabla en modo exclusivo. Evita que las transacciones simultáneas escriban un número mayor mientras intenta sincronizarse. (También bloquea temporalmente las escrituras inofensivas sin alterar el número máximo).

Pero no tiene en cuenta a los clientes que pueden haber obtenido números de secuencia de antemano sin ningún bloqueo en la tabla principal (lo que puede suceder). Para permitir eso, también, solo aumentar el valor actual de la secuencia, nunca disminuirlo. Puede parecer paranoico, pero está de acuerdo con la naturaleza de las secuencias y la defensa contra los problemas de concurrencia.

BEGIN; LOCK TABLE tbl IN EXCLUSIVE MODE; SELECT setval(''tbl_tbl_id_seq'', max(tbl_id)) FROM tbl HAVING max(tbl_id) > (SELECT last_value FROM tbl_tbl_id_seq); COMMIT;


Esta respuesta es una copia de mauro.

drop function IF EXISTS rebuilt_sequences() RESTRICT; CREATE OR REPLACE FUNCTION rebuilt_sequences() RETURNS integer as $body$ DECLARE sequencedefs RECORD; c integer ; BEGIN FOR sequencedefs IN Select DISTINCT(constraint_column_usage.table_name) as tablename, constraint_column_usage.column_name as columnname, replace(replace(columns.column_default,''''''::regclass)'',''''),''nextval('''''','''') as sequencename from information_schema.constraint_column_usage, information_schema.columns where constraint_column_usage.table_schema =''public'' AND columns.table_schema = ''public'' AND columns.table_name=constraint_column_usage.table_name AND constraint_column_usage.column_name = columns.column_name AND columns.column_default is not null ORDER BY sequencename LOOP EXECUTE ''select max(''||sequencedefs.columnname||'') from '' || sequencedefs.tablename INTO c; IF c is null THEN c = 0; END IF; IF c is not null THEN c = c+ 1; END IF; EXECUTE ''alter sequence '' || sequencedefs.sequencename ||'' minvalue ''||c ||'' start '' || c ||'' restart with '' || c; END LOOP; RETURN 1; END; $body$ LANGUAGE plpgsql; select rebuilt_sequences();


Estas funciones están plagadas de peligros cuando los nombres de secuencia, nombres de columnas, nombres de tablas o nombres de esquemas tienen caracteres divertidos, como espacios, signos de puntuación y similares. He escrito esto:

CREATE OR REPLACE FUNCTION sequence_max_value(oid) RETURNS bigint VOLATILE STRICT LANGUAGE plpgsql AS $$ DECLARE tabrelid oid; colname name; r record; newmax bigint; BEGIN FOR tabrelid, colname IN SELECT attrelid, attname FROM pg_attribute WHERE (attrelid, attnum) IN ( SELECT adrelid::regclass,adnum FROM pg_attrdef WHERE oid IN (SELECT objid FROM pg_depend WHERE refobjid = $1 AND classid = ''pg_attrdef''::regclass ) ) LOOP FOR r IN EXECUTE ''SELECT max('' || quote_ident(colname) || '') FROM '' || tabrelid::regclass LOOP IF newmax IS NULL OR r.max > newmax THEN newmax := r.max; END IF; END LOOP; END LOOP; RETURN newmax; END; $$ ;

Puede llamarlo para una sola secuencia pasándole el OID y devolverá el número más alto utilizado por cualquier tabla que tenga la secuencia como predeterminada; o puede ejecutarlo con una consulta como esta, para restablecer todas las secuencias en su base de datos:

select relname, setval(oid, sequence_max_value(oid)) from pg_class where relkind = ''S'';

Usando una calificación diferente, puede restablecer solo la secuencia en un determinado esquema, y ​​así sucesivamente. Por ejemplo, si desea ajustar secuencias en el esquema "público":

select relname, setval(pg_class.oid, sequence_max_value(pg_class.oid)) from pg_class, pg_namespace where pg_class.relnamespace = pg_namespace.oid and nspname = ''public'' and relkind = ''S'';

Tenga en cuenta que debido a cómo funciona setval (), no necesita agregar 1 al resultado.

Como nota final, debo advertir que algunas bases de datos parecen tener valores predeterminados que se vinculan a secuencias de manera que no permiten que los catálogos del sistema tengan información completa sobre ellas. Esto sucede cuando ves cosas como esta en psql''s / d:

alvherre=# /d baz Tabla «public.baz» Columna | Tipo | Modificadores ---------+---------+------------------------------------------------ a | integer | default nextval((''foo_a_seq''::text)::regclass)

Tenga en cuenta que la llamada nextval () en esa cláusula predeterminada tiene una conversión de texto :: además de la conversión :: regclass. Creo que esto se debe a que las bases de datos son pg_dump''ed de versiones anteriores de PostgreSQL. Lo que sucederá es que la función sequence_max_value () anterior ignorará dicha tabla. Para solucionar el problema, puede redefinir la cláusula DEFAULT para referirse a la secuencia directamente sin la conversión:

alvherre=# alter table baz alter a set default nextval(''foo_a_seq''); ALTER TABLE

Entonces psql lo muestra correctamente:

alvherre=# /d baz Tabla «public.baz» Columna | Tipo | Modificadores ---------+---------+---------------------------------------- a | integer | default nextval(''foo_a_seq''::regclass)

Tan pronto como lo hayas solucionado, la función funciona correctamente para esta tabla, así como para todas las demás que podrían usar la misma secuencia.


Este comando solo cambia el valor de la secuencia de la clave generada automáticamente en postgresql

ALTER SEQUENCE "your_sequence_name" RESTART WITH 0;

En lugar de cero, puede poner cualquier número desde el que desee reiniciar la secuencia.

el nombre de secuencia predeterminado será "TableName_FieldName_seq" . Por ejemplo, si el nombre de su tabla es "MyTable" y su nombre de campo es "MyID" , entonces su nombre de secuencia será "MyTable_MyID_seq" .

Esta respuesta es la misma que la respuesta de @ murugesanponappan, pero hay un error de sintaxis en su solución. no puede usar la sub consulta (select max()...) en el comando de alter . Para que tenga que usar un valor numérico fijo o una variable en lugar de una sub consulta.


Este problema ocurre conmigo cuando uso el marco de entidad para crear la base de datos y luego sembrar la base de datos con datos iniciales, esto hace que la secuencia no coincida.

Lo resolví creando un script para ejecutarlo después de sembrar la base de datos:

DO $do$ DECLARE tablename text; BEGIN -- change the where statments to include or exclude whatever tables you need FOR tablename IN SELECT table_name FROM information_schema.tables WHERE table_schema=''public'' AND table_type=''BASE TABLE'' AND table_name != ''__EFMigrationsHistory'' LOOP EXECUTE format(''SELECT setval(pg_get_serial_sequence(''''"%s"'''', ''''Id''''), (SELECT MAX("Id") + 1 from "%s"))'', tablename, tablename); END LOOP; END $do$


Esto restablecerá todas las secuencias del público sin hacer suposiciones sobre los nombres de tablas o columnas. Probado en la versión 8.4

CREATE OR REPLACE FUNCTION "reset_sequence" (tablename text, columnname text, sequence_name text) RETURNS "pg_catalog"."void" AS $body$ DECLARE BEGIN EXECUTE ''SELECT setval( '''''' || sequence_name || '''''', '' || ''(SELECT MAX('' || columnname || '') FROM '' || tablename || '')'' || ''+1)''; END; $body$ LANGUAGE ''plpgsql''; select table_name || ''_'' || column_name || ''_seq'', reset_sequence(table_name, column_name, table_name || ''_'' || column_name || ''_seq'') from information_schema.columns where column_default like ''nextval%'';


Intenta reindex .

ACTUALIZACIÓN: Como se señaló en los comentarios, esto fue en respuesta a la pregunta original.


La respuesta de Klaus es la más útil, excepto para un poco de error: tiene que agregar DISTINCT en la declaración de selección.

Sin embargo, si está seguro de que ningún nombre de tabla + columna puede ser equivalente para dos tablas diferentes, también puede usar:

select sequence_name, --PG_CLASS.relname, PG_ATTRIBUTE.attname reset_sequence(split_part(sequence_name, ''_id_seq'',1)) from PG_CLASS join PG_ATTRIBUTE on PG_ATTRIBUTE.attrelid = PG_CLASS.oid join information_schema.sequences on information_schema.sequences.sequence_name = PG_CLASS.relname || ''_'' || PG_ATTRIBUTE.attname where sequence_schema=''public'';

que es una extensión de la solución user457226 para el caso en que algún nombre de columna interesada no sea ''ID''.


Mi versión usa la primera, con algún error de comprobación ...

BEGIN; CREATE OR REPLACE FUNCTION reset_sequence(_table_schema text, _tablename text, _columnname text, _sequence_name text) RETURNS pg_catalog.void AS $BODY$ DECLARE BEGIN PERFORM 1 FROM information_schema.sequences WHERE sequence_schema = _table_schema AND sequence_name = _sequence_name; IF FOUND THEN EXECUTE ''SELECT setval( '''''' || _table_schema || ''.'' || _sequence_name || '''''', '' || ''(SELECT MAX('' || _columnname || '') FROM '' || _table_schema || ''.'' || _tablename || '')'' || ''+1)''; ELSE RAISE WARNING ''SEQUENCE NOT UPDATED ON %.%'', _tablename, _columnname; END IF; END; $BODY$ LANGUAGE ''plpgsql''; SELECT reset_sequence(table_schema, table_name, column_name, table_name || ''_'' || column_name || ''_seq'') FROM information_schema.columns WHERE column_default LIKE ''nextval%''; DROP FUNCTION reset_sequence(_table_schema text, _tablename text, _columnname text, _sequence_name text) ; COMMIT;


Para reiniciar toda la secuencia a 1 use:

-- Create Function CREATE OR REPLACE FUNCTION "sy_restart_seq_to_1" ( relname TEXT ) RETURNS "pg_catalog"."void" AS $BODY$ DECLARE BEGIN EXECUTE ''ALTER SEQUENCE ''||relname||'' RESTART WITH 1;''; END; $BODY$ LANGUAGE ''plpgsql''; -- Use Function SELECT relname ,sy_restart_seq_to_1(relname) FROM pg_class WHERE relkind = ''S'';


Pasé una hora tratando de obtener la respuesta de djsnowsill para trabajar con una base de datos utilizando tablas y columnas de Casos Mixtos, luego finalmente encontré la solución gracias a un comentario de Manuel Darveau, pero pensé que podía aclararlo un poco para todos:

CREATE OR REPLACE FUNCTION "reset_sequence" (tablename text, columnname text) RETURNS "pg_catalog"."void" AS $body$ DECLARE BEGIN EXECUTE format(''SELECT setval(pg_get_serial_sequence(''''%1$I'''', %2$L), (SELECT COALESCE(MAX(%2$I)+1,1) FROM %1$I), false)'',tablename,columnname); END; $body$ LANGUAGE ''plpgsql''; SELECT format(''%s_%s_seq'',table_name,column_name), reset_sequence(table_name,column_name) FROM information_schema.columns WHERE column_default like ''nextval%'';

Esto tiene el beneficio de:

  • no asumiendo que la columna de ID se escribe de una manera particular.
  • No asumiendo que todas las tablas tienen una secuencia.
  • trabajando para nombres de tablas / columnas de casos mixtos.
  • Usando el formato para ser más conciso.

Para explicarlo, el problema fue que pg_get_serial_sequence toma cadenas para resolver a qué se refiere, por lo que si lo hace:

"TableName" --it thinks it''s a table or column ''TableName'' --it thinks it''s a string, but makes it lower case ''"TableName"'' --it works!

Esto se logra usando ''''%1$I'''' en la cadena de formato, '''' hace que un apóstrofe 1$ signifique primero arg, y I decir entre comillas


Poniendolo todo junto

CREATE OR REPLACE FUNCTION "reset_sequence" (tablename text) RETURNS "pg_catalog"."void" AS $body$ DECLARE BEGIN EXECUTE ''SELECT setval( pg_get_serial_sequence('''''' || tablename || '''''', ''''id''''), (SELECT COALESCE(MAX(id)+1,1) FROM '' || tablename || ''), false)''; END; $body$ LANGUAGE ''plpgsql'';

id'' secuencia de '' id'' de la tabla dada (como suele ser necesario con django, por ejemplo).


Restablecer todas las secuencias de público

CREATE OR REPLACE FUNCTION "reset_sequence" (tablename text) RETURNS "pg_catalog"."void" AS $body$ DECLARE BEGIN EXECUTE ''SELECT setval( '''''' || tablename || ''_id_seq'''', '' || ''(SELECT id + 1 FROM "'' || tablename || ''" ORDER BY id DESC LIMIT 1), false)''; END; $body$ LANGUAGE ''plpgsql''; select sequence_name, reset_sequence(split_part(sequence_name, ''_id_seq'',1)) from information_schema.sequences where sequence_schema=''public'';


Restablecer todas las secuencias, no hay suposiciones sobre los nombres, excepto que la clave principal de cada tabla es "id":

CREATE OR REPLACE FUNCTION "reset_sequence" (tablename text, columnname text) RETURNS "pg_catalog"."void" AS $body$ DECLARE BEGIN EXECUTE ''SELECT setval( pg_get_serial_sequence('''''' || tablename || '''''', '''''' || columnname || ''''''), (SELECT COALESCE(MAX(id)+1,1) FROM '' || tablename || ''), false)''; END; $body$ LANGUAGE ''plpgsql''; select table_name || ''_'' || column_name || ''_seq'', reset_sequence(table_name, column_name) from information_schema.columns where column_default like ''nextval%'';


Si ve este error cuando está cargando datos SQL personalizados para la inicialización, otra forma de evitar esto es:

En lugar de escribir:

INSERT INTO book (id, name, price) VALUES (1 , ''Alchemist'' , 10),

Eliminar el id (clave principal) de los datos iniciales

INSERT INTO book (name, price) VALUES (''Alchemist'' , 10),

Esto mantiene sincronizada la secuencia de Postgres!


Sin embargo, otro plpgsql - se reinicia solo si max(att) > then lastval

do --check seq not in sync $$ declare _r record; _i bigint; _m bigint; begin for _r in ( SELECT relname,nspname,d.refobjid::regclass, a.attname, refobjid FROM pg_depend d JOIN pg_attribute a ON a.attrelid = d.refobjid AND a.attnum = d.refobjsubid JOIN pg_class r on r.oid = objid JOIN pg_namespace n on n.oid = relnamespace WHERE d.refobjsubid > 0 and relkind = ''S'' ) loop execute format(''select last_value from %I.%I'',_r.nspname,_r.relname) into _i; execute format(''select max(%I) from %s'',_r.attname,_r.refobjid) into _m; if coalesce(_m,0) > _i then raise info ''%'',concat(''changed: '',_r.nspname,''.'',_r.relname,'' from:'',_i,'' to:'',_m); execute format(''alter sequence %I.%I restart with %s'',_r.nspname,_r.relname,_m+1); end if; end loop; end; $$ ;

también comentando la línea --execute format(''alter sequence dará la lista, no restableciendo realmente el valor


Sugiero esta solución encontrada en postgres wiki. Actualiza todas las secuencias de tus tablas.

SELECT ''SELECT SETVAL('' || quote_literal(quote_ident(PGT.schemaname) || ''.'' || quote_ident(S.relname)) || '', COALESCE(MAX('' ||quote_ident(C.attname)|| ''), 1) ) FROM '' || quote_ident(PGT.schemaname)|| ''.''||quote_ident(T.relname)|| '';'' FROM pg_class AS S, pg_depend AS D, pg_class AS T, pg_attribute AS C, pg_tables AS PGT WHERE S.relkind = ''S'' AND S.oid = D.objid AND D.refobjid = T.oid AND D.refobjid = C.attrelid AND D.refobjsubid = C.attnum AND T.relname = PGT.tablename ORDER BY S.relname;

Cómo utilizar (desde postgres wiki):

  • Guarda esto en un archivo, di ''reset.sql''
  • Ejecute el archivo y guarde su salida de una manera que no incluya los encabezados habituales, luego ejecute esa salida. Ejemplo:

Ejemplo:

psql -Atq -f reset.sql -o temp psql -f temp rm temp

Artículo original (también con arreglo para la propiedad de secuencia) here


Un truco feo para arreglarlo usando algo de magia de shell, no es una gran solución pero podría inspirar a otros con problemas similares :)

pg_dump -s <DATABASE> | grep ''CREATE TABLE'' | awk ''{print "SELECT setval(#" $3 "_id_seq#, (SELECT MAX(id) FROM " $3 "));"}'' | sed "s/#/''/g" | psql <DATABASE> -f -


Vuelva a comprobar todas las secuencias en la función de esquema público

CREATE OR REPLACE FUNCTION public.recheck_sequence ( ) RETURNS void AS $body$ DECLARE _table_name VARCHAR; _column_name VARCHAR; _sequence_name VARCHAR; BEGIN FOR _table_name IN SELECT tablename FROM pg_catalog.pg_tables WHERE schemaname = ''public'' LOOP FOR _column_name IN SELECT column_name FROM information_schema.columns WHERE table_name = _table_name LOOP SELECT pg_get_serial_sequence(_table_name, _column_name) INTO _sequence_name; IF _sequence_name IS NOT NULL THEN EXECUTE ''SELECT setval(''''''||_sequence_name||'''''', COALESCE((SELECT MAX(''||quote_ident(_column_name)||'')+1 FROM ''||quote_ident(_table_name)||''), 1), FALSE);''; END IF; END LOOP; END LOOP; END; $body$ LANGUAGE ''plpgsql'' VOLATILE CALLED ON NULL INPUT SECURITY INVOKER COST 100;


antes no había probado todavía el código: a continuación publico la versión para el código sql para las soluciones Klaus y user457226 que funcionaron en mi PC [Postgres 8.3], con solo algunos pequeños ajustes para el Klaus uno y de mi versión para el usuario 457226 uno.

Solución de Klaus:

drop function IF EXISTS rebuilt_sequences() RESTRICT; CREATE OR REPLACE FUNCTION rebuilt_sequences() RETURNS integer as $body$ DECLARE sequencedefs RECORD; c integer ; BEGIN FOR sequencedefs IN Select constraint_column_usage.table_name as tablename, constraint_column_usage.table_name as tablename, constraint_column_usage.column_name as columnname, replace(replace(columns.column_default,''''''::regclass)'',''''),''nextval('''''','''') as sequencename from information_schema.constraint_column_usage, information_schema.columns where constraint_column_usage.table_schema =''public'' AND columns.table_schema = ''public'' AND columns.table_name=constraint_column_usage.table_name AND constraint_column_usage.column_name = columns.column_name AND columns.column_default is not null LOOP EXECUTE ''select max(''||sequencedefs.columnname||'') from '' || sequencedefs.tablename INTO c; IF c is null THEN c = 0; END IF; IF c is not null THEN c = c+ 1; END IF; EXECUTE ''alter sequence '' || sequencedefs.sequencename ||'' restart with '' || c; END LOOP; RETURN 1; END; $body$ LANGUAGE plpgsql; select rebuilt_sequences();

solución user457226:

--drop function IF EXISTS reset_sequence (text,text) RESTRICT; CREATE OR REPLACE FUNCTION "reset_sequence" (tablename text,columnname text) RETURNS bigint --"pg_catalog"."void" AS $body$ DECLARE seqname character varying; c integer; BEGIN select tablename || ''_'' || columnname || ''_seq'' into seqname; EXECUTE ''SELECT max("'' || columnname || ''") FROM "'' || tablename || ''"'' into c; if c is null then c = 0; end if; c = c+1; --because of substitution of setval with "alter sequence" --EXECUTE ''SELECT setval( "'' || seqname || ''", '' || cast(c as character varying) || '', false)''; DOES NOT WORK!!! EXECUTE ''alter sequence '' || seqname ||'' restart with '' || cast(c as character varying); RETURN nextval(seqname)-1; END; $body$ LANGUAGE ''plpgsql''; select sequence_name, PG_CLASS.relname, PG_ATTRIBUTE.attname, reset_sequence(PG_CLASS.relname,PG_ATTRIBUTE.attname) from PG_CLASS join PG_ATTRIBUTE on PG_ATTRIBUTE.attrelid = PG_CLASS.oid join information_schema.sequences on information_schema.sequences.sequence_name = PG_CLASS.relname || ''_'' || PG_ATTRIBUTE.attname || ''_seq'' where sequence_schema=''public'';


pg_get_serial_sequence se puede utilizar para evitar cualquier suposición incorrecta sobre el nombre de la secuencia. Esto restablece la secuencia en un disparo:

SELECT pg_catalog.setval(pg_get_serial_sequence(''table_name'', ''id''), (SELECT MAX(id) FROM table_name)+1);

O más concisamente:

SELECT pg_catalog.setval(pg_get_serial_sequence(''table_name'', ''id''), MAX(id)) FROM table_name;

Sin embargo, esta forma no puede manejar tablas vacías correctamente, ya que max (id) es nulo, y tampoco puede establecer el valor 0 porque estaría fuera del rango de la secuencia. Una solución para esto es recurrir a la sintaxis de ALTER SEQUENCE es decir

ALTER SEQUENCE table_name_id_seq RESTART WITH 1; ALTER SEQUENCE table_name_id_seq RESTART; -- 8.4 or higher

Pero ALTER SEQUENCE tiene un uso limitado porque el nombre de secuencia y el valor de reinicio no pueden ser expresiones.

Parece que la mejor solución para todos los propósitos es llamar a setval con falso como el tercer parámetro, lo que nos permite especificar el "siguiente valor a usar":

SELECT setval(pg_get_serial_sequence(''t1'', ''id''), coalesce(max(id),0) + 1, false) FROM t1;

Esto cumple todos mis casilleros:

  1. evita codificar el nombre de secuencia real
  2. maneja las tablas vacías correctamente
  3. Maneja tablas con datos existentes y no deja un agujero en la secuencia.

Finalmente, tenga en cuenta que pg_get_serial_sequence solo funciona si la secuencia es propiedad de la columna. Este será el caso si la columna de incremento se definió como un tipo de serial , sin embargo, si la secuencia se agregó manualmente, es necesario asegurarse de que ALTER SEQUENCE .. OWNED BY también se realiza.

es decir, si se usó serial tipo de serial para la creación de tablas, esto debería funcionar:

CREATE TABLE t1 ( id serial, name varchar(20) ); SELECT pg_get_serial_sequence(''t1'', ''id''); -- returns ''t1_id_seq'' -- reset the sequence, regardless whether table has rows or not: SELECT setval(pg_get_serial_sequence(''t1'', ''id''), coalesce(max(id),0) + 1, false) FROM t1;

Pero si las secuencias se agregaran manualmente:

CREATE TABLE t2 ( id integer NOT NULL, name varchar(20) ); CREATE SEQUENCE t2_custom_id_seq START WITH 1 INCREMENT BY 1 NO MINVALUE NO MAXVALUE CACHE 1; ALTER TABLE t2 ALTER COLUMN id SET DEFAULT nextval(''t2_custom_id_seq''::regclass); ALTER SEQUENCE t2_custom_id_seq OWNED BY t2.id; -- required for pg_get_serial_sequence SELECT pg_get_serial_sequence(''t2'', ''id''); -- returns ''t2_custom_id_seq'' -- reset the sequence, regardless whether table has rows or not: SELECT setval(pg_get_serial_sequence(''t2'', ''id''), coalesce(max(id),0) + 1, false) FROM t1;


SELECT setval... hace JDBC bork, así que aquí hay una manera compatible con Java de hacer esto:

-- work around JDBC ''A result was returned when none was expected.'' -- fix broken nextval due to poorly written 20140320100000_CreateAdminUserRoleTables.sql DO ''BEGIN PERFORM setval(pg_get_serial_sequence(''''admin_user_role_groups'''', ''''id''''), 1 + COALESCE(MAX(id), 0), FALSE) FROM admin_user_role_groups; END;'';


ALTER SEQUENCE sequence_name REINICIAR CON (SELECCIONE max (id) FROM nombre_tabla); No funciona

Copiado de @tardate respuesta:

SELECT setval(pg_get_serial_sequence(''table_name'', ''id''), MAX(id)) FROM table_name;


-- Login to psql and run the following -- What is the result? SELECT MAX(id) FROM your_table; -- Then run... -- This should be higher than the last result. SELECT nextval(''your_table_id_seq''); -- If it''s not higher... run this set the sequence last to your highest id. -- (wise to run a quick pg_dump first...) BEGIN; -- protect against concurrent inserts while you update the counter LOCK TABLE your_table IN EXCLUSIVE MODE; -- Update the sequence SELECT setval(''your_table_id_seq'', COALESCE((SELECT MAX(id)+1 FROM your_table), 1), false); COMMIT;

Fuente - Foro Rubí