pg_get_serial_sequence
pode ser usado para evitar suposições incorretas sobre o nome da sequência. Isso redefine a sequência de uma vez:
SELECT pg_catalog.setval(pg_get_serial_sequence('table_name', 'id'), (SELECT MAX(id) FROM table_name)+1);
Ou, mais concisamente:
SELECT pg_catalog.setval(pg_get_serial_sequence('table_name', 'id'), MAX(id)) FROM table_name;
No entanto, este formulário não pode manipular tabelas vazias corretamente, pois max (id) é nulo, e você também não pode definir o valor 0 porque estaria fora do intervalo da sequência. Uma solução alternativa para isso é recorrer à ALTER SEQUENCE
sintaxe ie
ALTER SEQUENCE table_name_id_seq RESTART WITH 1;
ALTER SEQUENCE table_name_id_seq RESTART; -- 8.4 or higher
Mas ALTER SEQUENCE
é de uso limitado, porque o nome da sequência e o valor de reinicialização não podem ser expressões.
Parece que a melhor solução para todos os fins é chamar setval
false com o terceiro parâmetro, permitindo especificar o "próximo valor a ser usado":
SELECT setval(pg_get_serial_sequence('t1', 'id'), coalesce(max(id),0) + 1, false) FROM t1;
Isso marca todas as minhas caixas:
- evita codificar o nome da sequência real
- lida com tabelas vazias corretamente
- lida com tabelas com dados existentes e não deixa um buraco na sequência
Por fim, observe que pg_get_serial_sequence
só funciona se a sequência pertencer à coluna. Este será o caso se a coluna de incremento tiver sido definida como um serial
tipo, no entanto, se a sequência foi adicionada manualmente, é necessário garantir que ALTER SEQUENCE .. OWNED BY
também seja realizada.
ou seja, se o serial
tipo foi usado para a criação da tabela, tudo deve 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;
Mas se as sequências foram adicionadas 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;