【Oracle設計】リレーションの方向性と循環参照の回避

オラクルデータベースの基本

~健全なテーブル関係が運用・開発・性能を守る~


■ はじめに

Oracleでデータベース設計を行う際、テーブル間の関係(リレーション)をどのように設計するかは、
性能・保守性・整合性に直結する極めて重要な要素です。

その中でも、リレーションの方向性を誤ったり、循環参照(相互参照)を含んだ構造は、
設計上のバグと言っても過言ではありません。

本記事では、リレーション設計の基本、循環参照がもたらす問題、正しい設計パターンを図解付きで丁寧に解説します。


■ 正しいリレーションとは?

リレーションは、通常「親 → 子(1:N)」の方向で設計されます。

たとえば、「部門」テーブルと「社員」テーブルがある場合、1つの部門に複数の社員が所属するため、社員テーブルに外部キーを持たせるのが正しい設計です。


📘【図1】1:N のリレーション(親→子)

DEPT(部門)          EMP(社員)
┌────────┐ ┌────────────┐
│DEPT_ID PK │ │EMP_ID PK │
│DEPT_NAME │ │ENAME │
└────────┘ │DEPT_ID FK◄──┐
└────────────┘
  • EMP.DEPT_ID は DEPT.DEPT_ID を参照
  • これは「親 → 子」の片方向リレーション

■ 循環参照とは?

循環参照とは、2つ以上のテーブルが互いに外部キー制約を持ち合う設計です。
これは一見データ整合性を高めているように見えますが、実際には多くの不都合を生み出します。


📘【図2】循環参照の例(NG構成)

Aテーブル                     Bテーブル
┌────────────┐ ┌────────────┐
│A_ID PK │ │B_ID PK │
│B_ID FK◄────┐ │A_ID FK ────┘
└────────────┘ └────────────┘
  • 双方が互いの主キーを参照している
  • CREATE TABLE時に制約の先後関係エラーが出やすい
  • INSERT時にNULLで仮登録 → UPDATEで埋める必要がある
  • DELETE時には循環的な依存関係で削除不可になることも

■ 循環参照による代表的な問題

項目問題の内容
CREATE TABLE の順序が複雑化制約の順序やNULL許容の工夫が必要
INSERT処理が難しくなる片方の値が確定しないとINSERTできない(NULL→UPDATEなどの対応が必要)
DELETE時に外部キー制約違反相互依存しているため削除順序が限定される
アプリケーションが複雑化登録順序や整合性チェックをアプリ側で補完する必要あり
論理モデルの可読性が低下ER図がスパゲッティ化し、メンテナンス性が著しく下がる

■ 回避策:外部キーの片方向設計を徹底する

循環参照を避けるには、外部キー制約は一方向(親 → 子)に限定することが最も有効です。
どうしても双方向の関係が業務上必要な場合は、どちらか片方はアプリケーションやビューで補完する方針にしましょう。


📘【図3】循環参照を回避した安全な設計

DEPT(部門)         EMP(社員)          PROJECT(プロジェクト)
┌────────┐ ┌────────────┐ ┌──────────────┐
│DEPT_ID PK │ │EMP_ID PK │ │PROJ_ID PK │
│DEPT_NAME │ │ENAME │ │ASSIGNEE_ID FK ────▶│EMP.EMP_ID
└────────┘ │DEPT_ID FK◄──┐ └──────────────┘
└────────────┘
  • EMPはDEPTを参照
  • PROJECTはEMPを参照
  • 片方向にのみ外部キー制約を設けており、循環参照はない

■ 正しいリレーション設計の原則

設計方針説明
外部キーは親 → 子の一方向に限定子テーブルにのみ外部キー制約を持たせる
循環参照は設計バグと考える業務要件であっても、アプリ側で補完すべき
相互参照が必要なら片方は参照だけにする外部キー制約を設定せず論理的な関連にとどめる
ビューや関数で双方向関係を補う外部キーで縛らずにロジックで整合性を担保する

■ 循環参照が必要なように見えるケースの対処法

例えば、ある業務で「社員が所属する部門」「部門の管理者が社員」などの相互関係がある場合、
以下のように、部門にある「管理者ID」は外部キー制約を張らず、論理的な関連とします


📘【図4】論理的な相互関係の実現(外部キー制約は片方向)

DEPT(部門)                 EMP(社員)
┌────────────┐ ┌────────────┐
│DEPT_ID PK │ │EMP_ID PK │
│MANAGER_ID │─────▶│ENAME │
└────────────┘ │DEPT_ID FK◄──┐
└────────────┘
  • DEPT.MANAGER_ID → EMP.EMP_ID は外部キー制約を張らない(論理的な結合)

■ Oracleで循環参照の確認方法(補足)

以下のビューを用いると、テーブル同士の依存関係の確認が可能です。

SELECT constraint_name, table_name, r_constraint_name
FROM user_constraints
WHERE constraint_type = 'R';
SELECT name, referenced_name, type, referenced_type
FROM user_dependencies
WHERE type = 'TABLE';

■ まとめ

  • Oracle設計では、外部キーの方向性を「親 → 子」に統一することが基本
  • 循環参照(相互参照)は設計ミスと見なし、必ず回避すべき
  • 論理的に双方向関係が必要でも、制約を片方向に留め、整合性はアプリケーションやビューで補完
  • 正しい設計は、運用・保守・性能すべてにおいて好影響をもたらす


[参考]
Oracle Database データベース開発ガイド 19c

コメント

タイトルとURLをコピーしました