質問 |
||
| QNo.3702103 | PostgreSQL serial型の質問 | |
|---|---|---|
| 質問者:kabukimomo | PostgreSQLで、自動採番(serial)について質問です。MAX_VALUEを超えた場合、MIN_VALUE(1)という記載がありますが、対象テーブル上に1が存在した場合は、どうなってしまうのでしょうか? 2が空いてた場合、2が使用されるのでしょうか? 4バイト(約21億なので、あまり問題がないかもしれませんが、)ユーザに、その質問を投げかけられ、困っております。 | |
困り度:
|
||
| 質問投稿日時: 08/01/22 02:41 |
||
回答 |
|
| ANo.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#DATAT... 引用: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で確認したので、 他のバージョンや、環境設定により異なると思います。 |
|---|---|
| 回答者:venzou | |
| 種類:回答 どんな人:一般人 自信:参考意見 |
|
| 回答日時: 08/01/22 12:56 |
|
| |
| この回答への補足 | この回答に補足をつける(質問者のみ) |
| この回答へのお礼 | この回答にお礼をつける(質問者のみ) |
回答 |
|
| ANo.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 |
|---|---|
| 回答者:alte_6 | |
| 種類:アドバイス どんな人:経験者 自信:自信あり |
|
| 回答日時: 08/01/22 11:40 |
|
| |
| この回答への補足 | この回答に補足をつける(質問者のみ) |
| この回答へのお礼 | この回答にお礼をつける(質問者のみ) |
回答 |
|
| ANo.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を使って、ご利用中のバージョンでも確認してみて下さい。 |
|---|---|
| 回答者:venzou | |
| 種類:回答 どんな人:一般人 自信:参考意見 |
|
| 回答日時: 08/01/22 04:34 |
|
| |
| この回答への補足 | この回答に補足をつける(質問者のみ) |
| この回答へのお礼 | この回答にお礼をつける(質問者のみ) |