• 締切済み

PostgreSQL serial型の質問

PostgreSQLで、自動採番(serial)について質問です。MAX_VALUEを超えた場合、MIN_VALUE(1)という記載がありますが、対象テーブル上に1が存在した場合は、どうなってしまうのでしょうか? 2が空いてた場合、2が使用されるのでしょうか? 4バイト(約21億なので、あまり問題がないかもしれませんが、)ユーザに、その質問を投げかけられ、困っております。

みんなの回答

  • venzou
  • ベストアンサー率71% (311/435)
回答No.3

#1です。 シーケンスには、CYCLE というパラメータがあるのですね。 早速、これも試してみました。 =========================================================== test=# alter sequence test_id_seq cycle; ALTER SEQUENCE test=# insert into test (data)values(10); INSERT 0 1 test=# select * from test;      id     | data ---------------------+------           1 |  1           2 |  2      2147483645 |  3      2147483646 |  4      2147483647 |  5 9223372036854775806 |  7 9223372036854775807 |  8           1 |  10 (8 行) =========================================================== 1 に戻りました。 id にUNIQUE制約付けてなかったので、登録されました。 過去のバージョンではデフォルトで UNIQUE になるようです。 http://www.postgresql.jp/document/pg732doc/user/datatype.html#DATATYPE-SERIAL 引用:PostgreSQL 7.3 より前のバージョンでは、serial は UNIQUE を暗黙指定していました。 10を削除して、UNIQUE制約を試します。 =========================================================== test=# delete from test where data=10; DELETE 1 test=# create unique index id_index on test (id); CREATE INDEX test=# insert into test (data)values(11); ERROR: duplicate key violates unique constraint "id_index" test=# insert into test (data)values(12); INSERT 0 1 test=# select * from test;      id     | data ---------------------+------           1 |  1           2 |  2      2147483645 |  3      2147483646 |  4      2147483647 |  5 9223372036854775806 |  7 9223372036854775807 |  8           3 |  12 (8 行) =========================================================== 11回目の追加は、UNIQUE制約に引っ掛りエラーです。 12回目の追加は、次の 3 が空いていたので、登録されました。 エラー発生時もカウントは加算されているようですね。 ----------------------------------------------------------- 話が、シーケンスの話になってしまいましたが。 serial型 の話に戻して、簡単にまとめてみます。 serial型 を使ったときに、自動で作られるシーケンスでは、 シーケンスの上限に達する前に、integer の上限でエラーが発生。 (これはリトライしても解決しない。) integer の上限に達する恐れがある場合は、何らかの対処が必要。 シーケンスを修正すれば、integerの範囲で、周回させる事も可能。 しかし、自動で空き番号を選択するような仕組みはない・・・と思います。 繰り返しますが、バージョン8.2.5で確認したので、 他のバージョンや、環境設定により異なると思います。

すると、全ての回答が全文表示されます。
  • alte_6
  • ベストアンサー率60% (9/15)
回答No.2

setvalしない限り1になりません。 シーケンスに定義し serialをinteger型にしデフォルトnextvalに置き換える事で可能かと思います。 CREATE SEQUENCE tablename_colname_seq MAXVALUE 2XXXXXXXXX CYCLE; CREATE TABLE tablename (  colname integer DEFAULT nextval('tablename_colname_seq') UNIQUE ); 2になるかどうかはバージョンによるようですが、 UNIQUE制約を付けてduplicateエラーが出る場合リトライする事で対応 可能かと思います。 http://www.postgresql.jp/document/pg732doc/user/datatype.html

すると、全ての回答が全文表示されます。
  • venzou
  • ベストアンサー率71% (311/435)
回答No.1

PostgreSQL 8.2.5 で確認しました。 まず、下記を参考に。 http://www.j-pal.ne.jp/murai/exp/posgre/no5.html シーケンスのMAX_VALUEですが、8バイトですね。 9223372036854775807 (7FFF FFFF FFFF FFFF) つまり、922京3372兆0368億5477万5807。京の単位ですね・・・ まず越える事はないでしょうが、実験してみました。 まず、integer の上限でエラーが出ました。 ================================================================= test=# insert into test (data)values(6); ERROR: integer out of range ================================================================= これは、serialが実際はinteger型で作られているからです。 ================================================================= test=# create table test (id serial, data integer); NOTICE: CREATE TABLE will create implicit sequence "test_id_seq" for serial col umn "test.id" CREATE TABLE test=# \d test;             テーブル "public.test" カラム |  型  |           修飾語 --------+---------+--------------------------------------------------- id   | integer | not null default nextval('test_id_seq'::regclass) data  | integer | ================================================================= シーケンスの上限はまだ先です。 idのカラムを、numericに変更して、先に進めます。 ================================================================= test=# alter table test alter id type numeric; ALTER TABLE test=# \d test             テーブル "public.test" カラム |  型  |           修飾語 --------+---------+--------------------------------------------------- id   | numeric | not null default nextval('test_id_seq'::regclass) data  | integer | ================================================================= シーケンスの上限でエラーが出ました。 ================================================================= test=# insert into test (data)values(9); ERROR: nextval: reached maximum value of sequence "test_id_seq" (92233720368547 75807) ================================================================= 因みに実験で追加したのは9件です。 setvalを使って、途中は飛ばしました。(^^; ================================================================= test=# select * from test;      id     | data ---------------------+------           1 |  1           2 |  2      2147483645 |  3      2147483646 |  4      2147483647 |  5 9223372036854775806 |  7 9223372036854775807 |  8 (7 行) ================================================================= 以上、実験終了。 >MAX_VALUEを超えた場合、MIN_VALUE(1)という記載がありますが 今回の実験では、MIN_VALUEには戻りませんでした。 この情報の出所は確かでしょうか?(^^; (バージョンによる違いかな?・・・) バージョン 8.2.5では、「エラーになる」が答えだと思います。 setvalを使って、ご利用中のバージョンでも確認してみて下さい。

すると、全ての回答が全文表示されます。

関連するQ&A