はじめに
Oracleで最もよく見るエラーの1つが ORA-00001:一意制約(UNIQUE制約)違反。
INSERT/UPDATE で突然エラーになり、原因が分かりづらいケースも多いです。
本記事では、UNIQUE制約でハマりやすいポイントと、ORA-00001の根本対策を実例付きで解説していきます。
ora-00001(一意制約違反)とは何か
UNIQUE制約は、指定した列(または複数列)に同じ値を登録できないようにする制約。
この例だと、同じ email を複数行入れようとすると ORA-00001 が発生します。
UNIQUE制約の基本構造(横長)
よくあるハマりポイント(原因)
① アプリ側の事前チェックが不十分
INSERT の前に「既に存在しないか?」をチェックしているのに、
マルチスレッドや同時アクセスで同時にINSERTしようとして競合するケース。
例(典型的な失敗パターン)
競合アクセスで発生するタイミング図
② 複合UNIQUE制約の理解不足
複数列に対する UNIQUE 制約は、組み合わせがユニークかどうかで判定されます。
例:
-
(100,1)
-
(100,2)
はOKだが、 -
(100,1) の重複はNG。
「片方の列だけを見て“重複してないから大丈夫”」と誤認するパターンが非常に多いです。
③ NULL が関係する場合(意外と知らない落とし穴)
UNIQUE制約は NULL は“比較不可”なので複数行存在できる。
例:
| value |
|---|
| NULL |
| NULL |
| 100 |
これはエラーになりません。
NULLは「値がわからない」であって「同じ」扱いではないため。
④ シーケンスを使っているのに重複が出るケース
「シーケンス使ってるのに ORA-00001?」という相談は非常に多いです。
主な原因:
-
シーケンスを複数環境で同期してしまい重複
-
INSERT時に別の値を入れてしまっている(バグ)
-
シーケンスキャッシュを大量の並列トランザクションが超えるケース ※レア
⑤ バッチ処理の再実行で重複INSERT
バッチ処理再実行時に、
「前回途中までINSERTされたデータ」が残っている場合に発生。
例:日次処理が途中で落ち、翌日再実行すると重複。
⑥ マスタ・トランザクションでの整合性不一致
アプリや上位システムのマスタデータが
「最新ではない」 or 「更新不足」
のために INSERT 先で重複が発生するケース。
金融・保険・基幹系で特に多いです。
シーケンス利用時の重複パターン図
ORA-00001 を回避する具体的な対策
① INSERT時は MERGE を活用する(最も安全)
-
存在しない場合 → INSERT
-
存在する場合 → 何もしない(更新してもOK)
同時実行でもエラーになりにくい。
② アプリ側で排他制御を導入
-
楽観ロック(version列)
-
悲観ロック(SELECT FOR UPDATE)
-
キューイング処理
などで同時更新を防ぐ。
③ UNIQUE制約の見直し(不要な制約を外す/複合にする)
要件上「片方の列だけでは一意でなくて良い」場合は、複合キーへ変更。
④ 既存データの重複を抽出してからINSERTする
バッチ処理で再実行される場合は以下のようにチェック。
⑤ SQL*Loader・大量INSERTはログ監視+リトライ
-
ログに「ORA-00001」が出たら重複行のみ再チェック
-
まとめてコミットせず、小分けにする
-
大量INSERTと並行でアプリが更新しないように運用調整
MERGEによる衝突回避イメージ図
実運用でのベストプラクティス(まとめ)
-
同時INSERTが起きやすい箇所は MERGE を使う
-
シーケンスを複数環境で同期させない
-
バッチ再実行時は必ず「前回分の残骸」がないか確認
-
UNIQUE制約は要件に合わせて“最小限”にする
-
既存データの重複を事前に棚卸ししてから運用開始
-
ログ監視で ORA-00001 の頻度を可視化する
これらを徹底するだけで、
一意制約違反(ORA-00001)の8割は防げます。
おわりに
一意制約はデータの整合性を守る重要な仕組みですが、
アプリ設計や並行アクセスの影響で思わぬところでトラブルになります。
本記事を参考に、UNIQUE制約の落とし穴を理解し、
ORA-00001 を根本から防げる環境設計を進めていきましょう。




