Instiq
第2章 · データベース設計と正規化·v1.0.0·更新 2026/7/10·読了目安 約15分

変更要約: 初版

2.4データ制約と整合性

この節の要点

実体を一意に識別する主キー候補キー、他表の主キーを参照する外部キー参照制約、任意の条件式で値を制限する検査制約(CHECK)を、整合性維持の設計判断として学びます。

正規化によって表を分解しても、表と表の関係を正しく維持し、不正な値の混入を防ぐ制約設計がなければ、データベースはすぐに整合性を失います。DB設計者は「この列は何を一意に識別すべきか」「この参照はどんな条件で壊れうるか」「アプリケーション側のバリデーションだけで十分か、DBMS側にも制約を持たせるべきか」を判断しなければなりません。この節では、主キー・外部キー・検査制約という3つの柱を、整合性維持の設計判断として学びます。

2.4.1主キーと候補キー

  • 候補キー=表の各行を一意に識別できる属性(の組)で、かつそこから属性を1つでも除くと一意性が崩れる最小限の組であるもの。1つの表に候補キーが複数存在することもある(例:社員表の社員IDとメールアドレスは、どちらも単独で行を一意に識別できる候補キー)。
  • 主キー=複数ある候補キーの中から、その表を代表する識別子として選ばれた1つ。他表からの参照(外部キー)にはこの主キーが使われる。主キーとして選ばれなかった候補キーは「代替キー」と呼ばれ、UNIQUE制約等で一意性のみ保証され続けることが多い。

2.4.2外部キーと参照制約

  • 外部キー=他表の主キー(または候補キー)を参照する列。参照制約(参照整合性制約)=外部キーの値は、参照先の表に実在する主キーの値か、あるいはNULLでなければならないという制約。これにより「存在しない親レコードを指す子レコード」の混入を防ぐ。
  • 参照先の行が削除・更新される際の挙動は参照アクションとして明示的に設計する:CASCADE(子も連動して削除/更新)・RESTRICT/NO ACTION(子が存在する限り親の削除/更新を拒否)・SET NULL(子の外部キーをNULLにする)。どれを選ぶかは業務要件(親削除時に子を残したいか、消したいか)で決まる。

2.4.3検査制約(CHECK)とその他の整合性制約

  • 検査制約(CHECK)=列(または行)が満たすべき任意の条件式をDBMSレベルで強制する制約(例:「在庫数量は0以上」「割引率は0〜100の範囲」)。アプリケーション層だけでバリデーションすると、別の経路(バッチ処理・直接のSQL実行等)からの不正な値混入を防げないため、DBMS側にも同じ制約を持たせる二重の防御が実務では重要。
  • NOT NULL制約=その列に値の欠落を許さない制約。一意性制約(UNIQUE)=主キー以外の列(代替キー等)に一意性のみを要求する制約。これらは主キー・外部キーほど構造を左右しないが、欠落や重複を許すべきでない業務ルールをDBMS側で機械的に保証するという点で参照制約・検査制約と同じ役割を担う。
試験ポイント

「候補キー=一意性を持つ最小限の属性組」「主キー=候補キーから選ばれた代表」「外部キー+参照制約=存在しない親を指す子レコードを防ぐ」「検査制約=DBMSレベルでの値の範囲・条件の強制」が最頻出です。参照アクション(CASCADE/RESTRICT/SET NULL)は業務要件次第で正解が変わるため、「親削除時に子データをどう扱いたいか」という業務ルールとセットで判断できるようにしておきましょう。

あるECサイトのデータベース設計者が、「注文」表と「注文明細」表の外部キー制約を設計しています。業務要件として「注文が取り消された場合、その注文に紐づく注文明細も自動的に削除してよい(明細だけが単独で存在する意味はない)」ため、注文明細の外部キー(注文ID)にはCASCADEを設定し、親の注文が削除されると明細も連動して削除される設計にしました。一方、「顧客」表と「注文」表の間では、「顧客を退会させても、監査・会計目的で過去の注文履歴は残さなければならない」という要件があるため、注文の外部キー(顧客ID)にはRESTRICT(またはSET NULL)を設定すべきです。仮にここでもCASCADEを設定してしまうと、顧客を削除した瞬間にその顧客の全注文履歴が失われ、会計監査に必要な記録が消失するという重大な事故になります。さらに、この設計者は「注文明細の数量は1以上でなければならない」という業務ルールをアプリケーション層のみでバリデーションしていましたが、ある日、バッチ処理による一括登録スクリプトがバリデーションを経由せず直接SQLでINSERTを行い、数量0の不正な注文明細が混入する障害が発生しました。この教訓から、アプリケーション層のバリデーションに加えて、注文明細表の数量列に「数量 >= 1」という検査制約(CHECK)をDBMS側にも設定することで、どの経路からの書き込みであっても不正な値の混入を防ぐ二重の防御を築くのが正しい対応です。このように、外部キーの参照アクションと検査制約の設計は、いずれも「どの経路から不正なデータが混入しうるか」を洗い出した上で、業務ルールに応じて個別に判断する必要があります。

参照アクション挙動適する業務要件
CASCADE親の削除/更新に子も連動する子が親なしに存在する意味がない場合(注文と注文明細等)
RESTRICT / NO ACTION子が存在する限り親の削除/更新を拒否子データを監査・会計目的で必ず保持したい場合
SET NULL親削除時に子の外部キーをNULLにする子を残しつつ親との関連だけ切り離したい場合
注意

ひっかけ: 「外部キーには常にCASCADEを設定すべき」は誤りです——監査・会計要件がある関連にCASCADEを設定すると、親の削除で本来残すべき履歴データまで消失する重大事故になります。また「アプリケーション層でバリデーションしていればDBMS側の検査制約は不要」も誤りで、バッチ処理や直接のSQL実行などアプリケーション層を経由しない書き込み経路からの不正な値混入を防ぐには、DBMS側の制約が必要です。

主キー/外部キー/参照制約の図。
正しさを制約で守る

2.4.4この節のまとめ

  • 候補キー=一意性を持つ最小限の属性組。主キー=その中から選ばれた代表識別子(他は代替キー)
  • 外部キー参照制約=存在しない親を指す子レコードを防ぐ。参照アクション(CASCADE/RESTRICT/SET NULL)は業務要件で選ぶ
  • 検査制約(CHECK)はアプリ層バリデーションだけでは防げない経路(バッチ・直接SQL等)からの不正値混入を防ぐ二重の防御

進捗の記録にはログインが必要です。

理解度チェック

(軽い確認用)

Q1. ECサイトの「注文」表と「注文明細」表の間で、「注文が取り消された場合、その注文明細も自動的に削除してよい」という業務要件がある。この要件を満たす外部キーの参照アクションとして最も適切なものはどれか。

Q2. 同じECサイトで、「顧客」表と「注文」表の間には「顧客を退会させても、監査・会計目的で過去の注文履歴は残さなければならない」という要件がある。この関連の外部キーにCASCADEを設定した場合に起こりうる問題として最も適切なものはどれか。

Q3. 「注文明細の数量は1以上でなければならない」という業務ルールをアプリケーション層のみでバリデーションしていたところ、バッチ処理が直接SQLでINSERTを行い、数量0の不正なデータが混入する障害が発生した。この再発防止策として最も適切なものはどれか。

理解度を確認第2章「データベース設計と正規化」の問題を解く