データベーススペシャリスト 2019年 午前2 問03
問題文
部課、係の階層関係から成る組織のデータモデルとして、モデルA~Cの三つの案が提出された。これらに対する解釈として、適切なものはどれか。組織階層における組織の位置を組織レベルと呼ぶ。組織間の階層関係は、親子として記述している。親と子は循環しないものとする。ここで、モデルの表記にはUMLを用い、{階層}は組織の親と子の関連が循環しないことを指定する制約記述である。

選択肢
ア:新しい組織レベルを設ける場合、どのモデルも変更する必要はない。
イ:どのモデルも、一つの子組織が複数の親組織から管轄される状況を記述できない。
ウ:モデルBを関係データベース上に実装する場合、親は子の組織コードを外部キーとする。
エ:モデルCでは、組織の親子関係が循環しないように制約を課す必要がある。(正解)
🔒 解説は解答すると表示されます
組織階層モデリング【午前2解説】
正解の理由
本問の適切な解釈は エ です。モデルCは「組織」と「組織構造(親・子の対)」という連関表(リレーション)で親子関係を管理する方式のため、同じ子組織に対して複数の親を登録でき、かつその連関の組み合わせにより循環(サイクル)が生じる可能性があります。したがって、モデルCでは親子関係が循環しないことを明示的に保証する制約(または検査)が必要です。モデルBも循環防止は必要ですが、本選択肢はモデルCについて述べており、正しい主張です。
解法ステップ
- 各モデルの構造を整理する(モデルA:階層ごとに別エンティティ、モデルB:自己参照、モデルC:連関表)。
- 「新しい組織レベル追加時のスキーマ変更」を各モデルに当てはめる(モデルAはエンティティ追加が必要、B/Cは不要)。
- 「多親(同一子に複数の親)」が表現可能かを確認(モデルBは親側が のため不可、モデルCは連関表に複数行を持てるため可)。
- 「実装上の外部キーの向き」を検証(自己参照モデルでは子が親の識別子を参照する)。
- 「循環の発生可能性と防止手段」を検討し、モデルCでの制約の必要性を確かめる。
選択肢別の誤答解説
-
ア: 誤り
モデルAは部・課・係それぞれを別エンティティで表現しているため、さらに深い「新しいレベル」を導入する際は新エンティティとそれに対応する関連を追加する必要がある(スキーマ変更)。一方、モデルB(自己参照)とモデルC(連関表)は同一テーブル構成でレベルをデータで表すため、スキーマ変更は不要でデータ追加のみで対応可能。 -
イ: 誤り
モデルBは親カーディナリティが なので一つの子に対して複数親を直接表せない(単一親ツリー)。しかしモデルCの連関表は親/子の組合せを行単位で保持するため、同一の子組織コードに対して複数行を入れれば「多親」を表現できる(DAGやネットワーク構造が可能)。 -
ウ: 誤り
モデルB(再帰的自己参照)を関係DBに実装する場合、通常は子レコードが親を参照する形で外部キーを持つ(例:組織テーブルに parent_org_code カラムを設け、それが同じ組織テーブルの組織コードを参照する)。選択肢の記述は外部キーの向きを逆にしており不正確です。例:CREATE TABLE organization ( org_code VARCHAR PRIMARY KEY, parent_org_code VARCHAR REFERENCES organization(org_code) ); -
エ: 正しい
モデルCは連関表により自由に親子ペアを追加できるため、誤って循環を作ることが可能である。従って「循環しないように制約を課す必要がある」という記述は妥当であり、本設問の正しい解釈です。
よくある誤解
- 「再帰モデル(モデルB)でも多親はOK」という誤解:モデルBの親側が の場合、子は最大1つの親しか参照できないため多親は表現できません。多親が必要なら連関表(モデルC)を使う。
- 「スキーマは常に変更不要」:データで階層を表すモデル(B/C)はスキーマ変更不要だが、階層ごとに別エンティティを持つ設計(モデルA)は新レベルでスキーマ変更が必要になる。
- 「循環はデータ上の問題なので放置してよい」:循環があると再帰走査が無限ループになったり集計が誤ったりするため、明示的な検査・制約が必須。
補足コラム
各モデルの長所・短所(要約)
-
モデルA(階層ごとのエンティティ)
長所:各階層に固有の属性を持たせやすく、概念的に分かりやすい。
短所:階層変更に弱く、レベル追加でスキーマ改修が必要。 -
モデルB(自己参照)
長所:スキーマがシンプルで深さに柔軟、単一親のツリー構造に最適。
短所:多親は表現不可。循環防止のチェックは必要。 -
モデルC(連関表)
長所:多親・任意の階層構造(DAG)を表現可能。柔軟性が高い。
短所:循環防止など整合性維持が複雑、問い合わせがやや煩雑。
循環防止の実装手法(代表例)
- DB側での検査:INSERT/UPDATE時に再帰CTEで祖先を辿り、自分自身が含まれていないか確認するトリガーを設ける。
- アプリケーション層で検査:変更前にグラフ探索で検証する。
- 代替設計:閉包表(祖先-子の全対)やパス文字列、左右番号法(nested set)等で整合性や高速検索を両立する方法もある。
簡単な再帰検索例(PostgreSQLの再帰CTE、モデルB向け)
WITH RECURSIVE ancestors(org_code, parent_org_code) AS (
SELECT org_code, parent_org_code FROM organization WHERE org_code = 'X'
UNION ALL
SELECT o.org_code, o.parent_org_code
FROM organization o
JOIN ancestors a ON o.org_code = a.parent_org_code
)
SELECT * FROM ancestors;
FAQ
Q1: モデルCで多親と同時に「階層レベル」を持たせられますか?
A1: 可能です。組織エンティティに組織レベル属性を持たせつつ、組織構造テーブルで親子を複数行により表現できます。ただしレベル値だけでは多親による順位判定があいまいになるので、業務ルールで解釈を定める必要があります。
A1: 可能です。組織エンティティに組織レベル属性を持たせつつ、組織構造テーブルで親子を複数行により表現できます。ただしレベル値だけでは多親による順位判定があいまいになるので、業務ルールで解釈を定める必要があります。
Q2: 循環防止はDBで完全に保証できますか?
A2: トリガーや制約(チェック+再帰クエリ)で実用上は保証できますが、厳密な一貫性を保つには設計・実装の注意が必要です。ロックや並行更新で競合が起きる場合、追加の排他制御が必要になることがあります。
A2: トリガーや制約(チェック+再帰クエリ)で実用上は保証できますが、厳密な一貫性を保つには設計・実装の注意が必要です。ロックや並行更新で競合が起きる場合、追加の排他制御が必要になることがあります。
Q3: 実務でどれを選べばよいですか?
A3: 単純な親子ツリー(各子は単一親)であればモデルBが扱いやすい。多親やネットワーク的関係が必要ならモデルC。モデルAは業務上「階層ごとに明確に異なる属性」がある場合に検討する。
A3: 単純な親子ツリー(各子は単一親)であればモデルBが扱いやすい。多親やネットワーク的関係が必要ならモデルC。モデルAは業務上「階層ごとに明確に異なる属性」がある場合に検討する。
関連キーワード: 組織構造、再帰リレーション、連関表、循環制約、多親表現

\ せっかくなら /
データベーススペシャリストを
クイズ形式で学習しませんか?
クイズ画面へ遷移する→
すぐに利用可能!

