データの整合性と品質を守るための「Oracle 制約 (Constraints)」。本記事では、開発や運用現場で頻出する制約の追加、削除、確認方法を、実機で使える SQL コマンドと共に解説します。
「制約名を忘れた」「ORA エラーの原因が分からない」といった悩みを解決し、正しい設計と実装手順をマスターしましょう。この記事一つで、Oracle Database 19c を前提とした制約操作の基本から応用までを網羅できます。
💰 【PR】Oracleエンジニアの市場価値、調べてみませんか?
Oracleのスキルは需要が高く、特定の資格や経験を持っていると年収が大幅にアップするケースがあります。まずはIT専門のエージェントで非公開求人をチェックしてみませんか?
結論:よく使う制約操作コマンド一覧(チートシート)
まずは、現場ですぐに使える主要コマンドの構文リストです。スニペットとして活用してください。
- テーブル作成時に定義
CREATE TABLE table_name (…, col_name data_type CONSTRAINT const_name PRIMARY KEY, …); - 既存テーブルへ追加
ALTER TABLE table_name ADD CONSTRAINT const_name CONSTRAINT_TYPE (column_name); - NOT NULL 制約の追加(MODIFY を使用)
ALTER TABLE table_name MODIFY (column_name CONSTRAINT const_name NOT NULL); - 制約の削除
ALTER TABLE table_name DROP CONSTRAINT const_name; - 制約の一時無効化 (データの大量ロード時などに利用)
ALTER TABLE table_name DISABLE CONSTRAINT const_name; - 制約の有効化
ALTER TABLE table_name ENABLE CONSTRAINT const_name;
Oracle 制約 (Constraints) とは?仕組みと重要性
制約 (Constraints) とは、データベース内のデータがビジネスルール(例:IDは重複しない、価格は正の数である等)に違反しないよう、Oracle Database 側で強制的にチェックする仕組みです。
- データの整合性保証: アプリケーションのバグや手作業によるミスデータ混入を防ぎます。
- パフォーマンス向上: オプティマイザが制約情報を利用して、より効率的な実行計画を作成する場合があります(例:主キーへのアクセス)。
5つの主要な制約
以下の表は、Oracle で頻繁に使用される 5 種類の制約の比較です。
| 制約の種類 | 日本語名 | 概要・役割 | NULL の扱い |
| PRIMARY KEY | 主キー制約 | 行を一意に識別する。表に1つのみ設定可能。 | 不許可 |
| UNIQUE | 一意性制約 | 重複値を禁止する。NULL は複数登録可能(※)。 | 許可 |
| NOT NULL | NOT NULL制約 | 値が必須であることを保証する。 | 不許可 |
| FOREIGN KEY | 外部キー制約 | 親表の値を参照し、整合性を保つ(参照整合性)。 | 許可 |
| CHECK | チェック制約 | 値が特定の条件式(例: price > 0)を満たすか検証。 | 許可 |
Note: UNIQUE 制約において、全ての列が NULL の場合は重複とはみなされませんが、Oracle の仕様上、NULL の扱いは慎重に行う必要があります。
【実践例】制約付きテーブル作成と検証用 SQL
ここでは、親子関係を持つ2つのテーブル(dept_demo と emp_demo)を作成し、各種制約を実装する完全な SQL 例を示します。
前提条件:
- 対象スキーマに
CREATE TABLE権限があること。 - SQL 内にマルチバイト文字(全角文字)を含めないことで、環境依存のエラーを防ぎます。
1. 親テーブルの作成 (主キー)
まずは参照される側の部署テーブルを作成します。
-- Create parent table: dept_demo
CREATE TABLE dept_demo (
dept_id NUMBER(4),
dept_name VARCHAR2(50) CONSTRAINT nn_dept_name NOT NULL,
loc VARCHAR2(50),
CONSTRAINT pk_dept_demo PRIMARY KEY (dept_id)
);
2. 子テーブルの作成 (外部キー・CHECK・DEFAULT・UNIQUE)
次に、参照する側の社員テーブルを作成します。
-- Create child table: emp_demo
CREATE TABLE emp_demo (
emp_id NUMBER(6),
emp_name VARCHAR2(50) CONSTRAINT nn_emp_name NOT NULL,
email VARCHAR2(100),
salary NUMBER(8, 2),
dept_id NUMBER(4),
hire_date DATE DEFAULT SYSDATE,
-- Define Constraints
CONSTRAINT pk_emp_demo PRIMARY KEY (emp_id),
CONSTRAINT uq_emp_email UNIQUE (email),
CONSTRAINT chk_emp_salary CHECK (salary > 0),
CONSTRAINT fk_emp_dept FOREIGN KEY (dept_id)
REFERENCES dept_demo (dept_id)
);
解説:
DEFAULT SYSDATE: データの挿入時に日付が指定されなかった場合、現在日時を自動入力します(厳密には制約ではありませんが、併用されることが多い機能です)。CONSTRAINT 制約名: 命名規則(例:pk_表名,fk_子表_親表)に従って名前を明示することを強く推奨します。省略するとシステム生成名(SYS_C0012345等)になり、管理が困難になります。
【実装】制約の追加・削除・有効化コマンド
テーブル作成後に要件変更で制約を操作する場合の手順です。
1. 制約の追加 (ADD / MODIFY)
テーブル作成後、例えば「給与の上限チェック」を追加したい場合:
-- Add CHECK constraint
ALTER TABLE emp_demo
ADD CONSTRAINT chk_salary_max CHECK (salary <= 1000000);
-- Add NOT NULL constraint (Modify syntax)
ALTER TABLE emp_demo
MODIFY (hire_date CONSTRAINT nn_hire_date NOT NULL);
2. 制約の削除 (DROP)
不要になった制約を削除します。
-- Drop Unique constraint
ALTER TABLE emp_demo
DROP CONSTRAINT uq_emp_email;
Warning:
PRIMARY KEYやUNIQUE制約を削除すると、それに対応して作成されていたインデックスも同時に削除される場合があります。運用中のシステムでは影響範囲の確認が必須です。
3. 制約の無効化・有効化 (DISABLE / ENABLE)
一時的に制約チェックを止めたい(大量データロード時のパフォーマンス優先など)場合に使用します。削除とは異なり、定義は残ります。
-- Disable constraint
ALTER TABLE emp_demo DISABLE CONSTRAINT fk_emp_dept;
-- Enable constraint (Validates existing data)
ALTER TABLE emp_demo ENABLE CONSTRAINT fk_emp_dept;
ENABLE実行時、既存データが制約に違反しているとエラーになり、有効化できません。その場合はENABLE NOVALIDATEオプションの使用を検討してください。
💰 【PR】Oracleエンジニアの市場価値、調べてみませんか?
Oracleのスキルは需要が高く、特定の資格や経験を持っていると年収が大幅にアップするケースがあります。まずはIT専門のエージェントで非公開求人をチェックしてみませんか?
【確認】設定済み制約を調べる SQL
設定されている制約を確認するには、データディクショナリビュー USER_CONSTRAINTS と USER_CONS_COLUMNS を結合して参照するのが確実です。
以下の SQL は、指定したテーブルの制約一覧と、それがどの列に紐付いているかを取得します。
-- Check constraints and columns
SELECT
uc.constraint_name,
uc.constraint_type,
ucc.column_name,
uc.search_condition,
uc.status
FROM
user_constraints uc
JOIN
user_cons_columns ucc
ON uc.constraint_name = ucc.constraint_name
WHERE
uc.table_name = 'EMP_DEMO'
ORDER BY
uc.constraint_type, uc.constraint_name;
CONSTRAINT_TYPE の読み方:
P: Primary KeyR: Referential Integrity (Foreign Key)U: Unique KeyC: Check (NOT NULL もここに含まれます)
SQL> SELECT
2 uc.constraint_name,
3 uc.constraint_type,
4 ucc.column_name,
5 uc.search_condition,
6 uc.status
7 FROM
8 user_constraints uc
9 JOIN
10 user_cons_columns ucc
11 ON uc.constraint_name = ucc.constraint_name
12 WHERE
13 uc.table_name = 'EMP_DEMO'
14 ORDER BY
15 uc.constraint_type, uc.constraint_name;
CONSTRAINT_NAME C COLUMN_NAME SEARCH_CONDITION STATUS
-------------------- - ----------------- ---------------------------- --------
CHK_EMP_SALARY C SALARY salary > 0 ENABLED
CHK_SALARY_MAX C SALARY salary <= 1000000 ENABLED
NN_EMP_NAME C EMP_NAME "EMP_NAME" IS NOT NULL ENABLED
NN_HIRE_DATE C HIRE_DATE "HIRE_DATE" IS NOT NULL ENABLED
PK_EMP_DEMO P EMP_ID ENABLED
FK_EMP_DEPT R DEPT_ID ENABLED
よくある ORA エラーと対処法 (トラブルシューティング)
制約に関連して頻発するエラーとその対処法です。
| エラーコード | 原因 | 対処法 |
| ORA-00001 | 一意制約違反 PKやUNIQUE列に重複値を入れようとした。 | 挿入データの値を確認するか、重複元のデータを修正・削除する。 |
| ORA-01400 | NULL挿入不可 NOT NULL列にNULLを入れようとした。 | INSERT文で値を指定する、またはDEFAULT値を設定する。 |
| ORA-02291 | 整合性制約違反(親キー未検出) 子表へのINSERT時、親表にないIDを指定した。 | 親表(dept_demo)に該当IDが存在するか確認し、先に親データを登録する。 |
| ORA-02292 | 整合性制約違反(子レコード発見) 親表のDELETE時、子表で参照されている。 | 子表(emp_demo)の関連レコードを先に削除するか、FKに ON DELETE CASCADE を設定する。 |
| ORA-02290 | チェック制約違反 CHECK条件を満たさない値を入れようとした。 | 入力値が条件式(例: salary > 0)を満たしているか確認する。 |
運用上の注意点とベストプラクティス
- 制約名の命名規則を統一するエラー発生時、ORA-00001: 一意制約 (SCOTT.SYS_C00123) に反しています と表示されると、どの列が原因か即座に分かりません。PK_EMP や UQ_EMP_EMAIL のように明示的な名前を付けましょう。
- 外部キー (FK) にはインデックスを作成する親表の主キーを更新・削除する際、子表の外部キー列にインデックスがないと、子表全体に対して表ロックが発生する可能性があります。デッドロック防止とパフォーマンスの観点から、外部キー列にはインデックス作成が推奨されます。
- 過剰な制約を避けるデータの品質は重要ですが、あまりに複雑な CHECK 制約はアプリケーションロジックで吸収すべき場合もあります。DB へのロード負荷とのバランスを考慮してください。
Oracle 制約に関する FAQ
Q1. 後から列に NOT NULL 制約を追加できますか?
A. はい、可能です。ただし、その列に既に NULL データが含まれている場合はエラー(ORA-02296)になります。事前に NULL データを更新(UPDATE)してから制約を追加してください。
Q2. 外部キー制約で ON DELETE CASCADE とは何ですか?
A. 親レコード(例:部署)を削除した際、それに紐づく子レコード(例:その部署の社員)も自動的に削除するオプションです。ON DELETE SET NULL(子レコードの値を NULL にする)もあります。便利な反面、意図せず大量のデータが消えるリスクがあるため、使用には注意が必要です。
Q3. 主キーとユニーク制約の違いは何ですか?
A. 主キー(Primary Key)は「行の識別子」であり、NULL 不可でテーブルに 1つしか作れません。ユニーク制約(Unique)は「重複排除」が目的で、NULL 可能、かつテーブルに複数作成可能です。
まとめ
Oracle データベースにおける制約は、堅牢なシステムを構築するための基礎です。
- 設計時: 5つの制約(PK, FK, UNIQUE, NOT NULL, CHECK)を適切に選定する。
- 実装時: メンテナンス性を考慮し、制約には必ず命名規則に従った名前を付ける。
- 運用時:
USER_CONSTRAINTSで設定を確認し、ORA エラー発生時はデータの実態と照らし合わせる。
正しいコマンドと知識を活用して、信頼性の高いデータベース設計を目指してください。
本記事は Oracle Database 19c を対象に解説します(他バージョンは画面や既定値が異なる場合があります)。
[参考]
Oracle Databaseデータベース管理者ガイド 19c
💰 【PR】Oracleエンジニアの市場価値、調べてみませんか?
Oracleのスキルは需要が高く、特定の資格や経験を持っていると年収が大幅にアップするケースがあります。まずはIT専門のエージェントで非公開求人をチェックしてみませんか?



コメント