外部キーの役割

このレッスンで分かること

  • 外部キー (FK) は子テーブルの値が親テーブルに存在することを保証します
  • FK が無いと「孤児レコード」が生まれて整合性が壊れます
  • FK は子側に書き、親側のカラムは PRIMARY KEY か UNIQUE

外部キーの役割 とは

テーブル間の関連性を定義する外部キーの役割について解説します。本レッスンでは、外部キーの役割 の基本から実際の使いどころまでを整理し、現場で迷わず使える形に落とし込みます。

なぜ重要か

複数のテーブルにまたがってデータを管理するとき、テーブル同士の 関係 を壊さないように守るのが外部キー (FOREIGN KEY) です。たとえば「注文」テーブルは「顧客」テーブルを参照しますが、もし存在しない顧客 ID が注文テーブルに入ってしまうと、その注文は誰の注文か分からなくなります。こうした「迷子のデータ」を生まないようにデータベース自身に番をさせる仕組みが外部キーであり、参照整合性 (referential integrity) の土台になります。

用語の整理

外部キーを語るときに最初に押さえたい言葉は次の通りです。

用語役割
親テーブル値の正解を持つcustomers
子テーブル親の値を借りるorders
参照先カラム親側で一意 (PK か UNIQUE)customers.id
外部キー列子側に置く参照列orders.customer_id
参照整合性子の FK 値が親に存在 (または NULL)customer_idcustomers.id に必ず存在

ER 図でイメージする

diagram (will load when visible)

図の関係を箇条書きで整理すると、次の通りです。

  • customers は親、orders は子
  • orders.customer_idcustomers.id を参照する
  • orders.product_idproducts.id を参照する
  • 矢印は子から親へ
  • FK は 常に子テーブル に書く

図の矢印は「子から親へ向かう参照」を示しています。外部キーは子テーブル側に書き、「この値は親テーブルのこのカラムに必ず存在しなければならない」と宣言します。

FK が無いとどうなるか

まずは FK を設定しないテーブルで何が起こるかを観察します。

SQL クエリ

CREATE TABLE customers (id INT PRIMARY KEY, name TEXT); CREATE TABLE orders (id INT PRIMARY KEY, customer_id INT, total INT); INSERT INTO customers VALUES (1, '田中'); INSERT INTO orders VALUES (10, 1, 3000), -- OK (11, 99, 5000); -- 99 番の顧客は存在しない

この状態でも DB はエラーを出しません。orders.customer_id = 99 のレコードはどの顧客とも結びつかない孤児レコード (orphan) になります。後で SELECT ... FROM orders JOIN customers ... をしても 99 番の注文は消えてしまい、売上集計が合わなくなります。

FK を入れた場合

外部キーを設定すると DB 自身が不整合を拒否してくれます。

SQL クエリ

CREATE TABLE customers (id INT PRIMARY KEY, name TEXT); CREATE TABLE orders ( id INT PRIMARY KEY, customer_id INT REFERENCES customers(id), total INT ); INSERT INTO orders VALUES (11, 99, 5000); -- ERROR: insert or update on table "orders" violates foreign key constraint

これが外部キーの最大の効果です。アプリ側のバリデーションを忘れても、DB レイヤで弾いてくれるため安全網になります。

外部キーは「親に存在する値しか子に入れない」というシンプルな約束。これが守られているテーブル群は、JOIN・集計・削除のどれを取っても矛盾しません。

外部キーは便利ですが、大量データの一括投入時はパフォーマンス低下の原因にもなります。バッチ処理では一時的に制約を外して投入し、最後に整合性チェックする運用もあります。

実装時のチェックリスト

実務でテーブル設計をするときは次の点を必ず確認します。

  • 親テーブルの参照先カラムは PRIMARY KEY か UNIQUE になっているか
  • 親テーブルは子テーブルより先に作成されているか (CREATE 順序)
  • 子テーブルの FK 列は親テーブルと同じ型・同じ長さか (INT と BIGINT を混ぜない)
  • NULL を許容するか NOT NULL にするか業務要件で決めたか
  • ON DELETE / ON UPDATE のポリシーを意図的に選んだか

どれか 1 つでも欠けると、後から修正コストが膨らみます。特にカラム型ミスマッチはエラーメッセージが分かりにくく、原因特定に時間がかかるトラップなので注意です。

関係を読み解くコツ

初学者が ER 図を見るときに混乱しやすいのが「矢印の向き」と「親子の認識」です。一般的なルールとして、矢印は 子から親に向かって描かれます が、図によっては逆向きで描く流派もあります。実装上のポイントは次のとおりです。

  • FK は 常に子テーブル に書く (orders に customer_id REFERENCES customers が入る)
  • 親側には「子から参照されている」という事実を表す制約は何も書かない
  • アプリの ORM で belongs_to :customer のように親への所属を宣言するのは子側

テーブル定義を読むときは「REFERENCES がある列を持つ側が子」と覚えるとブレません。

この章のポイント

ここまでの要点 FK は子側に REFERENCES 親(列) で書く。親列は PK か UNIQUE。型の長さも合わせる。FK は孤児レコードを防ぐ最後の砦。

まとめ

  • 外部キーは親テーブルに存在する値しか子テーブルに入れさせない仕組み
  • 子テーブルの「孤児レコード」を未然に防ぎ、JOIN や集計の正確さを担保する
  • 親側のカラムは PRIMARY KEY か UNIQUE である必要がある
  • FK を入れるとアプリ側のバグでも DB が最後の砦になる
  • 矢印やキーワードに惑わされず「REFERENCES を書く側が子」と覚える

次のレッスン

次は FOREIGN KEY制約の設定 です。テーブル間の関連性を設定するFOREIGN KEY制約について解説します。

事前確認 — 進む前に次の 3 つができることを確認しましょう。

  1. 外部キーの役割 の要点を自分の言葉で説明できる
  2. このレッスンの最小コード (または操作手順) を見ずに書ける
  3. 練習問題やクイズで間違えた箇所を読み直して理解した

理解度チェック (30 秒)

Q. 外部キーの役割 とは何か、1 文で説明してください。

この章のポイント

A. 本文の「このレッスンで分かること」または冒頭の説明文を見直し、自分の言葉で要約できれば OK。詰まったら本レッスンの最初の H2 セクションを読み返してみましょう。

関連レッスン

テーブル構造

schema.sql

CREATE TABLE customers ( id INT PRIMARY KEY, name TEXT NOT NULL ); CREATE TABLE orders ( id INT PRIMARY KEY, customer_id INT NOT NULL, total INT NOT NULL ); INSERT INTO customers (id, name) VALUES (1, '田中'), (2, '佐藤'), (3, '鈴木'); INSERT INTO orders (id, customer_id, total) VALUES (101, 1, 3000), (102, 2, 5000), (103, 1, 1500), (104, 99, 8000); -- 99番の顧客は存在しない (orphan)

期待される出力

idnametotal
101田中3000
102佐藤5000
103田中1500

ヒント

query.sql
query.sql
学習モード
コードの実行結果
データベースを初期化中...