LoginSignup
35
29

More than 5 years have passed since last update.

PostgreSQLのシーケンスのnextvalの挙動

Last updated at Posted at 2015-11-14

この記事はPostgreSQL9.4をベースに書いています。

create sequencestart 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 なようだ。

create_sequnceした直後
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)

setvalした直後
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_calledtrue になるようだ。

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)
35
29
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
35
29