この記事はPostgreSQL9.4をベースに書いています。
create sequence で start with 1 と指定すると、最初に nextval() した時に 1 が返ってくる。
mydb=# create sequence hoge start with 1;
CREATE SEQUENCE
mydb=# select nextval('hoge');
nextval
---------
1
(1 row)
ここまでは良くて、次に値をリセットしたくて setval('hoge',1) した後で nextval('hoge') すると 2 が返ってきてファッ!?となった。
mydb=# select setval('hoge',1);
setval
--------
1
(1 row)
mydb=# select nextval('hoge');
nextval
---------
2
(1 row)
それならばと、0 をセットしてみるが、範囲外と怒られてしまう。
mydb=# select setval('hoge',0);
ERROR: setval: value 0 is out of bounds for sequence "hoge" (1..9223372036854775807)
それぞれの状態を調べてみると、create sequenceした直後は is_called の値が false だが、 setval した直後は true なようだ。
mydb=# select * from hoge;
sequence_name | last_value | start_value | increment_by | max_value | min_value | cache_value | log_cnt | is_cycled | is_called
---------------+------------+-------------+--------------+---------------------+-----------+-------------+---------+-----------+-----------
hoge | 1 | 1 | 1 | 9223372036854775807 | 1 | 1 | 0 | f | f
(1 row)
mydb=# select * from hoge;
sequence_name | last_value | start_value | increment_by | max_value | min_value | cache_value | log_cnt | is_cycled | is_called
---------------+------------+-------------+--------------+---------------------+-----------+-------------+---------+-----------+-----------
hoge | 1 | 1 | 1 | 9223372036854775807 | 1 | 1 | 0 | f | t
(1 row)
create sequence は、nextval() したタイミングで is_called が true になるようだ。
mydb=# create sequence hoge start with 1;
CREATE SEQUENCE
mydb=# select nextval('hoge');
nextval
---------
1
mydb=# select * from hoge;
sequence_name | last_value | start_value | increment_by | max_value | min_value | cache_value | log_cnt | is_cycled | is_called
---------------+------------+-------------+--------------+---------------------+-----------+-------------+---------+-----------+-----------
hoge | 1 | 1 | 1 | 9223372036854775807 | 1 | 1 | 32 | f | t
(1 row)
mydb=# select nextval('hoge');
nextval
---------
2
(1 row)
調べたら、setval には第3引数に is_called が指定できるようだ。デフォルトが true なのは select setval('hoge', select MAX(id) from huga); とかする時はその方が良いからかな。
mydb=# select setval('hoge',1,false);
setval
--------
1
(1 row)
mydb=# select nextval('hoge');
nextval
---------
1
(1 row)
alter sequence restart with しても is_called には false が設定されるようだ。忘れた頃に setval してハマる気がするので今後はこっち使うようにした方が良いかな。
mydb=# alter sequence hoge restart with 1;
ALTER SEQUENCE
mydb=# select * from hoge;
sequence_name | last_value | start_value | increment_by | max_value | min_value | cache_value | log_cnt | is_cycled | is_called
---------------+------------+-------------+--------------+---------------------+-----------+-------------+---------+-----------+-----------
hoge | 1 | 1 | 1 | 9223372036854775807 | 1 | 1 | 0 | f | f
(1 row)
mydb=# select nextval('hoge');
nextval
---------
1
(1 row)