外部キーの役割
このレッスンで分かること
- 外部キー (FK) は子テーブルの値が親テーブルに存在することを保証します
- FK が無いと「孤児レコード」が生まれて整合性が壊れます
- FK は子側に書き、親側のカラムは PRIMARY KEY か UNIQUE
外部キーの役割 とは
テーブル間の関連性を定義する外部キーの役割について解説します。本レッスンでは、外部キーの役割 の基本から実際の使いどころまでを整理し、現場で迷わず使える形に落とし込みます。
なぜ重要か
複数のテーブルにまたがってデータを管理するとき、テーブル同士の 関係 を壊さないように守るのが外部キー (FOREIGN KEY) です。たとえば「注文」テーブルは「顧客」テーブルを参照しますが、もし存在しない顧客 ID が注文テーブルに入ってしまうと、その注文は誰の注文か分からなくなります。こうした「迷子のデータ」を生まないようにデータベース自身に番をさせる仕組みが外部キーであり、参照整合性 (referential integrity) の土台になります。
用語の整理
外部キーを語るときに最初に押さえたい言葉は次の通りです。
| 用語 | 役割 | 例 |
|---|---|---|
| 親テーブル | 値の正解を持つ | customers |
| 子テーブル | 親の値を借りる | orders |
| 参照先カラム | 親側で一意 (PK か UNIQUE) | customers.id |
| 外部キー列 | 子側に置く参照列 | orders.customer_id |
| 参照整合性 | 子の FK 値が親に存在 (または NULL) | customer_id は customers.id に必ず存在 |
ER 図でイメージする
図の関係を箇条書きで整理すると、次の通りです。
customersは親、ordersは子orders.customer_idはcustomers.idを参照するorders.product_idはproducts.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 つができることを確認しましょう。
- 外部キーの役割 の要点を自分の言葉で説明できる
- このレッスンの最小コード (または操作手順) を見ずに書ける
- 練習問題やクイズで間違えた箇所を読み直して理解した
理解度チェック (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)
期待される出力
| id | name | total |
|---|---|---|
| 101 | 田中 | 3000 |
| 102 | 佐藤 | 5000 |
| 103 | 田中 | 1500 |