- データベース
PostgreSQL integer out of rangeの原因と直し方
ERROR: integer out of range は、integer 型(-2,147,483,648〜2,147,483,647)に収まらない値を作ろうとしたときのエラーです。 多いのは次の3つです。
| 原因 | エラー文 | 直し方 |
|---|---|---|
| serial の ID が上限に届いた | nextval: reached maximum value of sequence "..." (2147483647) |
列を bigint に。シーケンスも bigint に |
| 掛け算・足し算の途中であふれた | integer out of range |
片方を ::bigint にしてから計算 |
| アプリから大きな値を入れた | integer out of range、value "..." is out of range for type integer |
列を bigint に |
確認環境:PostgreSQL 16.15、psycopg 3.3.6、PostgreSQL JDBC Driver 42.7.2(確認日 2026年10月11日)。
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「PostgreSQL integer out of rangeの原因と直し方」
原因1:serial の ID が上限に届いた
=> SELECT setval('ior_id_seq', 2147483646); -- 上限の手前まで進める
=> INSERT INTO ior (v) VALUES (1) RETURNING id;
id
------------
2147483647
=> INSERT INTO ior (v) VALUES (2) RETURNING id;
ERROR: nextval: reached maximum value of sequence "ior_id_seq" (2147483647)
serial の場合、エラー文は integer out of range ではなく、シーケンスの上限のエラーになりました。 serial は「integer の列」と「AS integer のシーケンス」を作るためです(PostgreSQL 公式ドキュメント)。シーケンスが bigint で、列が integer の場合は、integer out of range になりました。
| 列 | シーケンス | 上限を超えたときのエラー |
|---|---|---|
integer(serial) |
integer | nextval: reached maximum value of sequence |
| integer | bigint(手で作った) | integer out of range |
あとどれくらい残っているか
SELECT sequencename, data_type, last_value,
round(100.0 * coalesce(last_value, 0) / max_value, 4) AS used_pct
FROM pg_sequences;
data_type が integer のシーケンスで、used_pct が大きいものが要注意です。テストや移行でシーケンスを大きく進めた、1日に大量の行を入れては消す、といったテーブルでは、行数が少なくても番号だけが進みます。
落とし穴:列を bigint にしても、serial のシーケンスは integer のまま
ALTER TABLE ior ALTER COLUMN id TYPE bigint;
=> SELECT sequencename, data_type, max_value FROM pg_sequences WHERE sequencename = 'ior_id_seq';
sequencename | data_type | max_value
--------------+-----------+------------
ior_id_seq | integer | 2147483647 ← シーケンスは integer のまま
=> INSERT INTO ior (v) VALUES (3) RETURNING id;
ERROR: nextval: reached maximum value of sequence "ior_id_seq" (2147483647)
列を bigint に変えても、serial が作ったシーケンスの型は変わらず、同じエラーが続きました。 シーケンスも変えます。
ALTER SEQUENCE ior_id_seq AS bigint;
=> INSERT INTO ior (v) VALUES (3) RETURNING id;
id
------------
2147483648 ← 動いた
| 列の作り方 | ALTER COLUMN ... TYPE bigint のあと |
|---|---|
serial |
シーケンスは integer のまま。ALTER SEQUENCE ... AS bigint が別に必要 |
GENERATED ALWAYS AS IDENTITY |
シーケンスも bigint になった(確認環境) |
新しく作るテーブルは、最初から bigint GENERATED ALWAYS AS IDENTITY(または bigserial)にしておくのが確実です。公式ドキュメントでも、テーブルの寿命の間に 2^31 個を超える ID を使う見込みがあるなら、bigserial を使うよう書かれています。serial と IDENTITY の違いは、関連記事の「PostgreSQL連番|serialとIDENTITYの違いとsetval修正」で扱っています。
外部キーの列も忘れずに
注文テーブルの customer_id のように、この ID を参照している子のテーブルの列も integer のままだと、ID が上限を超えた行を参照するときに、子のテーブル側で同じエラーになります。親と子の列を一緒に変えます。
bigint への変更にかかる時間とロック
3,000,000 行(214MB)のテーブルで、ALTER TABLE ... ALTER COLUMN id TYPE bigint を実行しました。
| 項目 | 結果(確認環境) |
|---|---|
| かかった時間 | 2.4 秒 |
| テーブルの作り直し | あり(pg_relation_filenode の値が変わった) |
| 実行中のロック | AccessExclusiveLock |
| 実行中の別の接続の SELECT | canceling statement due to lock timeout(lock_timeout = '1s' で待たせたとき) |
integer から bigint への変更は、テーブル全体を作り直し、その間は SELECT も待たされました。 公式ドキュメントでも、型の変更は原則としてテーブルとインデックスの作り直しが必要で、ALTER TABLE は ACCESS EXCLUSIVE のロックを取るとされています。時間は行数・インデックスの数・ディスクの速さで変わるので、本番と同じくらいのデータで、事前に時間を測るのが安全です。作り直しの間は、一時的にディスクも余分に使います。
| 対策 | 内容 |
|---|---|
| 上限に届く前に変える | pg_sequences で残りを定期的に確認する |
| メンテナンスの時間に実行 | 止められる時間に合わせる |
lock_timeout を付けて実行 |
ほかの処理を長く止めない(取れなければやり直す) |
原因2:掛け算・足し算の途中であふれた
=> SELECT 50000 * 50000;
ERROR: integer out of range
=> SELECT 50000::bigint * 50000;
?column?
------------
2500000000
=> SELECT 2147483647 + 1;
ERROR: integer out of range
integer どうしの計算の結果は integer なので、途中であふれました。 単価×数量のような計算は、片方を ::bigint(または ::numeric)にしてから計算します。
| 計算 | 結果の型 | あふれるか |
|---|---|---|
int * int |
integer | あふれる |
int::bigint * int |
bigint | あふれない |
sum(int の列) |
bigint | 確認環境では 2147483647 を2つ足して 4294967294 と動いた |
sum は integer の列でも bigint で返るので、合計ではあふれません。あふれるのは、合計する前の、1行ごとの掛け算です。
原因3:大きな値を入れた
=> INSERT INTO ior (id, v) VALUES (1, 3000000000);
ERROR: integer out of range
=> INSERT INTO ior (id, v) VALUES (1, '3000000000');
ERROR: value "3000000000" is out of range for type integer
=> INSERT INTO ior3 VALUES (40000); -- smallint の列
ERROR: smallint out of range
文字列として渡すと、value "..." is out of range for type integer という別の文になりました。 smallint(-32,768〜32,767)では smallint out of range です。
Java 側でも起きる
| 操作 | 結果(確認環境) |
|---|---|
bigint の列の値 2147483648 を rs.getInt() |
PSQLException: Bad value for type int : 2147483648 |
同じ値を rs.getLong() |
2147483648 |
integer の列に setLong(1, 3000000000L) |
ERROR: integer out of range(SQLState 22003) |
DB の列を bigint に変えたら、Java の int の変数・getInt も long・getLong に変えます。 DB だけ変えても、アプリの読み取りで止まります。
確認の手順(チェックリスト)
| 順番 | 確認すること | 方法 |
|---|---|---|
| 1 | どのエラー文か | nextval: reached maximum(シーケンス)か integer out of range |
| 2 | ID なら、残りはどれくらいか | pg_sequences の last_value と max_value |
| 3 | 計算なら | 1行ごとの掛け算を ::bigint に |
| 4 | bigint に変える | 列とシーケンスの両方、外部キーの列も |
| 5 | 変更の時間とロック | 同じくらいのデータで事前に測る |
| 6 | アプリ | int・getInt を long・getLong に |
よくある質問
Q. SQLSTATE は何ですか。
A. integer out of range は 22003(numeric_value_out_of_range)です。シーケンスの上限のエラーは 2200H(sequence_generator_limit_exceeded)でした。
Q. ID を最初から振り直せばよいですか。 A. 使われていない番号から振り直す方法もありますが、ほかのテーブルやアプリが ID を保持していると、整合性が崩れます。bigint に変えるのが確実です。
まとめ
- integer(約21億)に収まらない値を作ったエラー
- serial の ID は、シーケンスの上限のエラー(
nextval: reached maximum value)で出る - 列を bigint にしても、serial のシーケンスは integer のまま。
ALTER SEQUENCE ... AS bigintも実行する - bigint への変更はテーブルを作り直し、SELECT も止まる。事前に時間を測る
- 計算は1行ごとの掛け算であふれる。
::bigintにしてから計算(sumは bigint) - Java の
getIntもgetLongに
参考・出典
確認日はいずれも 2026年10月11日です。
- PostgreSQL 16 Documentation「Numeric Types」(Serial Types):https://www.postgresql.org/docs/16/datatype-numeric.html
- PostgreSQL 16 Documentation「ALTER TABLE」:https://www.postgresql.org/docs/16/sql-altertable.html
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「PostgreSQL integer out of rangeの原因と直し方」
株式会社RJC ― SI事業・SES事業・AI駆動開発。RJCは一緒に成長を楽しめる会社です。
WE ARE HIRING
RJCで一緒に開発しながら、
成長を楽しみませんか?
RJCは、Web・モバイル・AIを活用した開発プロジェクトで、テックリードやPM・PMOも活躍するシステム開発会社です。会社を知る、待遇を確かめる、話を聞いてみる。気になるところ見てみてください!
- 127日年間休日
- 12時間平均残業時間
- 毎日ガチャ遊びココロも大切にする福利厚生。アマギフなどの賞品ラインナップ!
ほかにも、チケットレストラン、書籍読み放題、2年ごとの慰労報奨(休暇 or 金一封)、11期連続の黒字決算。