pg_get_serial_sequence
peut être utilisé pour éviter toute hypothèse incorrecte sur le nom de la séquence. Cela réinitialise la séquence en une seule fois:
SELECT pg_catalog.setval(pg_get_serial_sequence('table_name', 'id'), (SELECT MAX(id) FROM table_name)+1);
Ou plus précisément:
SELECT pg_catalog.setval(pg_get_serial_sequence('table_name', 'id'), MAX(id)) FROM table_name;
Cependant, ce formulaire ne peut pas gérer correctement les tables vides, car max (id) est nul, et vous ne pouvez pas non plus définir val 0 car il serait hors de portée de la séquence. Une solution pour cela consiste à recourir à la ALTER SEQUENCE
syntaxe, à savoir
ALTER SEQUENCE table_name_id_seq RESTART WITH 1;
ALTER SEQUENCE table_name_id_seq RESTART; -- 8.4 or higher
Mais ALTER SEQUENCE
son utilité est limitée car le nom de séquence et la valeur de redémarrage ne peuvent pas être des expressions.
Il semble que la meilleure solution polyvalente soit d'appeler setval
avec false comme 3e paramètre, ce qui nous permet de spécifier la "prochaine valeur à utiliser":
SELECT setval(pg_get_serial_sequence('t1', 'id'), coalesce(max(id),0) + 1, false) FROM t1;
Cela coche toutes mes cases:
- évite de coder en dur le nom de la séquence réelle
- gère correctement les tables vides
- gère les tables avec des données existantes et ne laisse pas de trou dans la séquence
Enfin, notez que cela pg_get_serial_sequence
ne fonctionne que si la séquence appartient à la colonne. Ce sera le cas si la colonne d'incrémentation a été définie comme un serial
type, mais si la séquence a été ajoutée manuellement, il est nécessaire de s'assurer qu'elle ALTER SEQUENCE .. OWNED BY
est également effectuée.
c'est-à-dire si le serial
type a été utilisé pour la création de table, cela devrait fonctionner:
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;
Mais si des séquences ont été ajoutées manuellement:
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;