pg_get_serial_sequence
kann verwendet werden, um falsche Annahmen über den Sequenznamen zu vermeiden. Dies setzt die Sequenz auf einmal zurück:
SELECT pg_catalog.setval(pg_get_serial_sequence('table_name', 'id'), (SELECT MAX(id) FROM table_name)+1);
Oder genauer:
SELECT pg_catalog.setval(pg_get_serial_sequence('table_name', 'id'), MAX(id)) FROM table_name;
Dieses Formular kann jedoch leere Tabellen nicht korrekt verarbeiten, da max (id) null ist und Sie auch nicht 0 setzen können, da es außerhalb des Bereichs der Sequenz liegen würde. Eine Problemumgehung besteht darin, auf die ALTER SEQUENCE
Syntax zurückzugreifen, d. H.
ALTER SEQUENCE table_name_id_seq RESTART WITH 1;
ALTER SEQUENCE table_name_id_seq RESTART; -- 8.4 or higher
Dies ALTER SEQUENCE
ist jedoch von begrenztem Nutzen, da der Sequenzname und der Neustartwert keine Ausdrücke sein können.
Es scheint, dass die beste Allzwecklösung darin besteht, setval
false als dritten Parameter aufzurufen , um den "nächsten zu verwendenden Wert" anzugeben:
SELECT setval(pg_get_serial_sequence('t1', 'id'), coalesce(max(id),0) + 1, false) FROM t1;
Dies erfüllt alle meine Kriterien:
- vermeidet die Hardcodierung des tatsächlichen Sequenznamens
- behandelt leere Tabellen korrekt
- behandelt Tabellen mit vorhandenen Daten und hinterlässt keine Lücke in der Sequenz
Beachten Sie schließlich, dass dies pg_get_serial_sequence
nur funktioniert, wenn die Sequenz der Spalte gehört. Dies ist der Fall, wenn die inkrementierende Spalte als serial
Typ definiert wurde. Wenn die Sequenz jedoch manuell hinzugefügt wurde, muss sichergestellt werden, dass sie ALTER SEQUENCE .. OWNED BY
auch ausgeführt wird.
Wenn also der serial
Typ für die Tabellenerstellung verwendet wurde, sollte dies alles funktionieren:
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;
Aber wenn Sequenzen manuell hinzugefügt wurden:
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;