pg_get_serial_sequence
può essere utilizzato per evitare ipotesi errate sul nome della sequenza. Questo reimposta la sequenza in un colpo solo:
SELECT pg_catalog.setval(pg_get_serial_sequence('table_name', 'id'), (SELECT MAX(id) FROM table_name)+1);
O più concisamente:
SELECT pg_catalog.setval(pg_get_serial_sequence('table_name', 'id'), MAX(id)) FROM table_name;
Tuttavia, questo modulo non è in grado di gestire correttamente le tabelle vuote, poiché max (id) è nullo e non è possibile impostare setval 0 perché non rientra nell'intervallo della sequenza. Una soluzione alternativa per questo è ricorrere alla ALTER SEQUENCE
sintassi cioè
ALTER SEQUENCE table_name_id_seq RESTART WITH 1;
ALTER SEQUENCE table_name_id_seq RESTART; -- 8.4 or higher
Ma ALTER SEQUENCE
è di utilità limitata perché il nome della sequenza e il valore di riavvio non possono essere espressioni.
Sembra che la migliore soluzione per tutti gli usi sia chiamare setval
con false come terzo parametro, permettendoci di specificare il "prossimo valore da usare":
SELECT setval(pg_get_serial_sequence('t1', 'id'), coalesce(max(id),0) + 1, false) FROM t1;
Questo spunta tutte le mie caselle:
- evita di codificare il nome effettivo della sequenza
- gestisce correttamente i tavoli vuoti
- gestisce le tabelle con dati esistenti e non lascia un buco nella sequenza
Infine, nota che pg_get_serial_sequence
funziona solo se la sequenza è di proprietà della colonna. Ciò avverrà se la colonna di incremento è stata definita come un serial
tipo, tuttavia se la sequenza è stata aggiunta manualmente è necessario assicurarsi che ALTER SEQUENCE .. OWNED BY
venga eseguita anche.
cioè se il serial
tipo è stato usato per la creazione di tabelle, tutto dovrebbe funzionare:
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;
Ma se le sequenze sono state aggiunte 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;