setval関数でシーケンスの現在値を変更する
PostgreSQLでシーケンスの現在値を変更するには、setval関数を使用する。
SELECT setval('シーケンス名', 値);
たとえばSERIAL型のidカラムを持つitemsテーブルのシーケンスitems_id_seqを100に設定する場合は以下のように実行する。
SELECT setval('items_id_seq', 100);
setval
--------
100
(1 row)
SELECT nextval('items_id_seq');
nextval
---------
101
(1 row)
setval実行後にnextvalを呼び出すと、指定した値の次の値(101)が返る。
これはsetvalの第3引数is_calledのデフォルト値がtrueであり、指定した値がすでに払い出し済みとして扱われるためである。
is_calledを指定して次のnextvalで指定値そのものを返す
次にnextvalを呼び出したときに指定値そのものを返したい場合は、第3引数にfalseを指定する。
SELECT setval('items_id_seq', 200, false);
setval
--------
200
(1 row)
SELECT nextval('items_id_seq');
nextval
---------
200
(1 row)
ALTER SEQUENCE RESTARTでシーケンスの現在値を変更する
ALTER SEQUENCE文のRESTART WITH句でも、シーケンスの現在値を変更できる。
ALTER SEQUENCE items_id_seq RESTART WITH 500;
SELECT nextval('items_id_seq');
nextval
---------
500
(1 row)
ALTER SEQUENCE RESTART WITHは、次のnextvalで指定値そのものを返す点がsetval(is_calledのデフォルトtrue)と異なる。
RESTARTに値を指定しない場合は、シーケンスの開始値にリセットされる。
開始値はCREATE SEQUENCEで定義した値(SERIAL型の場合は1)であり、ALTER SEQUENCE ... START WITHで変更していればその値になる。
ALTER SEQUENCE items_id_seq RESTART;
SELECT nextval('items_id_seq');
nextval
---------
1
(1 row)
テーブルの最大idにシーケンスを同期する
CSVインポートなどでidを明示的に指定してデータを挿入する場合を考える。
この場合、シーケンスの現在値とテーブルの最大idにずれが生じる。
ずれを解消するには、setvalにテーブルの最大idを渡して同期する。
SELECT setval('items_id_seq', (SELECT MAX(id) FROM items));
setval
--------
1000
(1 row)
SELECT nextval('items_id_seq');
nextval
---------
1001
(1 row)
setvalのis_calledはデフォルトでtrueのため、次のnextvalは最大idの次の値(1001)を返し、主キーの重複を避けられる。
テーブルが空でMAX(id)がNULLになる場合、setvalにそのままNULLを渡すと更新されずに終わる。COALESCE関数でNULLのときの初期値を指定すると、テーブルが空でも安全に実行できる。
SELECT setval('items_id_seq', (SELECT COALESCE(MAX(id), 1) FROM items));
pg_sequencesビューでシーケンスの現在値を確認する
変更後のシーケンスの現在値は、pg_sequencesビューのlast_valueカラムで確認できる。
SELECT sequencename, last_value
FROM pg_sequences
WHERE sequencename = 'items_id_seq';
sequencename | last_value
--------------+------------
items_id_seq | 1001
(1 row)
