pg_get_serial_sequence
có thể được sử dụng để tránh mọi giả định không chính xác về tên trình tự. Điều này đặt lại chuỗi trong một lần chụp:
SELECT pg_catalog.setval(pg_get_serial_sequence('table_name', 'id'), (SELECT MAX(id) FROM table_name)+1);
Hay chính xác hơn:
SELECT pg_catalog.setval(pg_get_serial_sequence('table_name', 'id'), MAX(id)) FROM table_name;
Tuy nhiên, biểu mẫu này không thể xử lý các bảng trống một cách chính xác, vì max (id) là null và bạn cũng không thể đặt giá trị 0 vì nó sẽ nằm ngoài phạm vi của chuỗi. Một cách giải quyết cho vấn đề này là sử dụng ALTER SEQUENCE
cú pháp tức là
ALTER SEQUENCE table_name_id_seq RESTART WITH 1;
ALTER SEQUENCE table_name_id_seq RESTART; -- 8.4 or higher
Nhưng ALTER SEQUENCE
được sử dụng hạn chế vì tên trình tự và giá trị khởi động lại không thể là biểu thức.
Có vẻ như giải pháp đa năng tốt nhất là gọi setval
với false là tham số thứ 3, cho phép chúng tôi chỉ định "giá trị tiếp theo sẽ sử dụng":
SELECT setval(pg_get_serial_sequence('t1', 'id'), coalesce(max(id),0) + 1, false) FROM t1;
Điều này đánh dấu vào tất cả các hộp của tôi:
- Tránh mã hóa cứng tên trình tự thực tế
- xử lý các bảng trống chính xác
- xử lý các bảng với dữ liệu hiện có và không để lại lỗ hổng trong chuỗi
Cuối cùng, lưu ý rằng pg_get_serial_sequence
chỉ hoạt động nếu chuỗi được sở hữu bởi cột. Đây sẽ là trường hợp nếu cột tăng được xác định là một serial
loại, tuy nhiên nếu trình tự được thêm bằng tay thì cần phải đảm bảo ALTER SEQUENCE .. OWNED BY
cũng được thực hiện.
tức là nếu serial
loại được sử dụng để tạo bảng, thì tất cả sẽ hoạt động:
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;
Nhưng nếu trình tự được thêm bằng tay:
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;