pg_get_serial_sequence
se puede usar para evitar suposiciones incorrectas sobre el nombre de la secuencia. Esto restablece la secuencia en una sola toma:
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, este formulario 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 ALTER SEQUENCE
sintaxis, 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
es de uso limitado porque el nombre de secuencia y el valor de reinicio no pueden ser expresiones.
Parece que la mejor solución para todo uso es llamar setval
a falso como el tercer parámetro, lo que nos permite especificar el "siguiente valor a utilizar":
SELECT setval(pg_get_serial_sequence('t1', 'id'), coalesce(max(id),0) + 1, false) FROM t1;
Esto cumple todos mis requisitos:
- evita codificar el nombre de secuencia real
- maneja las tablas vacías correctamente
- maneja tablas con datos existentes y no deja un hueco 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 serial
tipo, sin embargo, si la secuencia se agregó manualmente, es necesario asegurarse de ALTER SEQUENCE .. OWNED BY
que también se realice.
es decir, si serial
se utilizó el tipo para la creación de la tabla, 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 agregaron 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;