• 締切済み

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

  • postgreSQLのCOPY コマンド&serial型について。

    はじめまして。 最近からpostgreSQLを使ってデータベースを作っています。初めてのデータベース作成なので、少し手間取っていますが、宜しくお願いします。 テキストエディタを使って、タブ区切りで保存したファイルは、postgreSQLに、\copyコマンドでテーブルの中へ 流し込むことができると思いますが、テーブルを作成した際に、 CREATE TABLE ***(←テーブル名) (id SERIAL PRIMARY KEY,○○ △△,..........,); とテーブルを作ったのですが、1列目のSERIALが邪魔をするのか、COPYコマンドを使ってもテーブル内にデータが入っていきません・・・ エラーは『": can't parse "ne 119, pg_atoi: error in "』と返ってきます。 タブ区切りテキストファイルで、一括登録する際、serial型でうまく自動発番できるファイルの書き方とかありますか? 現在、仕事でデータベースを作っているのですが、扱っているデータの数が、12万件近くあるので、全てを手動で登録するのは、ちょっとキツイです・・・ 回答の方、宜しくお願いします。(質問の内容が、うまく伝わっていなかったら、ゴメンナサイ。)

  • serial型について

    Postgresql7.2.4で user:postgresにより CREATE TABLE test (id serial PRIMARY KEY,num INT4) というテーブルを作成し、 GRANT ALL ON test TO PUBLIC と権限を与えました。 そしてPHP4よりuser:nobodyで INSERT INTO test (num) VALUES (1) というクエリを実行しようとすると ERROR: test_id_seq.nextval: you don't have permissions to set sequence wash_h_test_id_seq in test.php とでます。 しかし INSERT INTO test (id,num) VALUES (1,1) とするとちゃんとデータベースに反映されます。 PHPで、このユーザーからserialを使った自動連番で 書き込めるようにするにはどうすればいいのでしょうか。

  • serialの値をINSERT時に取得する方法

    PostgreSQL8.3系を使っています。 PostgreSQLのserial型を使って、連番を意識せずINSERTして登録しているのですが、直前に登録した連番(serial)が知りたいことがありまして、 簡単に取得する方法がわかりません。 気になる点ですが書きこんだ後、他から書き込みがあった場合の直前は他のデータになると思うので、書き込んだ直後のserialフィールドのmax値はあてにならないと考えますが、詳しい方教えてください。 書きこんだ直後についでに何か取得できる(書きこんだときのserial値がわかる)方法はあるのでしょうか?

  • PerlDBIでのserial型の使い方

    PostgreSQLの8.0.2をPerlを使い、PerlDBIとして使っています。 自動的に番号をカウントアップしながら付与してくれる列を作りたくて、テーブル作成時にserial型を指定しました。 ところが、INSERTの際にその項目になんと入力していいのかわかりません。 省略すれば勝手に入ってくれるのかと思ったら permission denied for sequence filetable_fileno_seq at dbupdate.pl 155 とエラーが出てしまいます。 その155行目には $sth = $dbh->do("insert into $table values ('$list[$count]->[0]','$list[$count]->[1]','$list[$count]->[2]','$today','$today')"); といれています。 ちなみにテーブルは text、text、real、date、date、serial というならびになっています。 serialの列を入れる前までは上のSQL文で問題なかったのですが、serial型の列を追加してからは上記のようなエラーが出るようになりました。 何が原因なのかさっぱりわかりません。 教えていただければ幸いです

    • ベストアンサー
    • Perl
  • postgreSQLで扱えるデータ量

    postgreSQLの7.2や7.3で扱えるデータ量の上限はどんな制限があるかどなたかご存知でしょうか?ユーザ会のリリース情報で6.5でテーブルが2GBまでの制限があるということはわかったのですが、他に情報がなくよくわかりません。 対象OSはLinuxです。

  • ExcelにPostgreSQLのデータを取り込むには

    以下のサイトを参考にして、ODBC接続によるExcelへのPostgreSQLデータ取り込みを試みました。 「PostgreSQL ODBCによるアプリケーション接続」 http://allabout.co.jp/internet/database/closeup/CU20050219A/index.htm 「2. ExcelにPostgreSQLのテーブルのデータを取り込む手順」 http://allabout.co.jp/internet/database/closeup/CU20050219A/index2.htm ODBCの設定自体はたぶんうまくいったと思うのですが、いざExcelからPostgreSQLを取り込もうとすると、「このデータソースには表示できるテーブルがありません」というメッセージが表示されてしまいます。 接続先のDBには、テーブルは存在しています。 試しに、Accessでも以下のサイトの手順で試して見ましたが、「テーブルのリンク」画面に対象となるテーブルが1件も表示されません。 「3. AccessにPostgreSQLのテーブルのデータを取り込む手順」 http://allabout.co.jp/internet/database/closeup/CU20050219A/index3.htm テーブルとのリンクをはるために他にも何か設定は必要でしょうか? PostgreSQLは8.0.1、Officeは2003を使用しています。 接続は自分のPC内にあるOfficeから同じく自分のPC内にあるPostgreSQLへ接続しに行こうとしています。 よきアドバイスをいただけると助かります。 以上、よろしくお願いいたします。

  • postgresqlでのトランザクションについて

    postgresqlで、「WARNING  進行中のトランザクションがありません」のエラーが出てしまいました。 これはそのままの意味だと思うのですが 直す方法がわかりません。 ワーニングなので、、、といいたいところですが、そうもいかず。 apのログで、トランザクション関係の辺りを見ましたところ、 トランザクションを開始し、 TABLEをDROPしようとしましたが、存在しなかった(ようだ)。 (PQexecがエラーでリターン) 存在しないけれど、commit してトランザクションを終わらせている。 のが原因かなと思いました。 なので、PQexec()がエラーの場合はcommitしなければいいのかと はずしましたが結果は同じでした。 トランザクションが無いのだからrollbackもいらないですよね。 そこで質問ですが drop文、1ステップのSQL実行も明示的にトランザクションの処理をしたほうがいいのでしょうか? このワーニングは通常のトランザクションの処理の中で、どういう時にでるのでしょうか? oracleとpostgresqlの明示的・暗黙的な制御に戸惑っています。 (oracleからpostgresqlに移行することになりました) 叱咤でも何でもかまいませんので、アドバイスよろしくお願いいたします。

  • AUTO_INCREMENTの扱いについて

    MySQL 5.6を使用しています。 ユーザーテーブルがあるとします。 ユーザーテーブルにある「ユーザーID」はinsert時にAUTO_INCREMENTで自動採番されます。 ユーザーテーブルの別のカラムで「作成ユーザID」というカラムがあります。insertしたユーザーのユーザーIDを保持するカラムです。 すでにユーザーテーブルにいるユーザー(管理者)がinsertした場合はいいのですが、 自信で自分のユーザーを登録できる機能もあります。 その場合、まだ作成されてないユーザID(AUTO_INCREMENTで自動採番されるユーザーID)をどうやって参照したらいいでしょうか?

    • ベストアンサー
    • MySQL
  • PostgreSQLで一致した順にソート

    いつもお世話になっております。 早速質問させていただきます。 <memberテーブル> birthday(生年月日) graduate_cd(学歴コード) prefecture_cd(都道府県コード) があります。 <pointテーブル> min_age_cd(最小年齢コード) max_age_cd(最大年齢コード) graduate_cd(学歴コード) prefecture_cd(都道府県コード) があります。 memberテーブルのbirthdayは以下の式で年齢を割り出しています。 extract(year from age(now(), birthday)) as age やりたいことは・・・ (1) point.min_age_cd<=member.age and max_age_cd>=point.max_age_cd の場合マッチ。 (2) point.graduate_cd=member.graduate_cd の場合マッチ。 (3) point.prefecture_cd=member.prefecture_cd の場合マッチ。 ただ、point.prefecture_cdには、カンマ区切りで複数の prefecture_cdが格納されていますので、正規表現になるのでしょか? 正規表現の方法も教えていただきたいです。 (1)~(3)のマッチした数が多い順にソートをしたいと思っています。 皆さま、ご教授お願いいたします。 <環境> OS:Linux PostgreSQL Version:7.3.18 PHP Version:4.3.2

  • Postgresqlのインストーラーについて

    Postgresqlのインストーラーについて こんにちは。初めて質問させていただきます、初心者プログラマです。 現在、仕事上でアプリ開発を行い、postgresqlを使っています。 その完成した、アプリをインストールする場合、postgresqlもインストールしなければなりません。 ですが、ユーザーの方にpostgresqlのインストーラーを使用して、セットアップしていただくには、 少々難易度が高いのではと思っています。 そこで、ユーザーの方には簡単にpostgresqlをインストールしていただける手法を模索しております。 どなたか良い方法がございましたら、ご教授お願い致します。 今検討しているのが、postgresqlソースを修正し、それを元にコンパイルして、setup.exeみたいなものができないかなと思っております・・・。 今のバイナリファイルは拡張子がexeなのでmsiみたいにコマンドラインでオプションが使えれば簡単にできそうなのですが・・・。